From b12a56e5491eea7c273b39ca1deac26e0e14e22d Mon Sep 17 00:00:00 2001 From: Refael Ackermann Date: Tue, 12 Mar 2019 17:53:41 -0400 Subject: [PATCH 1/3] tools: replace GYP with GYP3 v6.0.3 (1/2) Refs: https://github.com/refack/GYP/tree/6.0.3 --- tools/gyp/.gitignore | 3 + tools/gyp/.travis.yml | 77 + tools/gyp/AUTHORS | 15 - tools/gyp/DEPS | 23 - tools/gyp/LICENSE | 1 + tools/gyp/OWNERS | 1 - tools/gyp/PRESUBMIT.py | 126 - tools/gyp/Pipfile | 14 + tools/gyp/Pipfile.lock | 70 + tools/gyp/README.md | 8 +- tools/gyp/azure-pipelines.yml | 26 + tools/gyp/buildbot/buildbot_run.py | 136 - tools/gyp/buildbot/commit_queue/OWNERS | 6 - tools/gyp/buildbot/commit_queue/README | 3 - .../gyp/buildbot/commit_queue/cq_config.json | 15 - tools/gyp/codereview.settings | 6 - tools/gyp/gyp.bat | 5 - tools/gyp/{pylib/gyp => gyp/MSVS}/MSVSNew.py | 262 +- .../{pylib/gyp => gyp/MSVS}/MSVSSettings.py | 45 +- .../{pylib/gyp => gyp/MSVS}/MSVSToolFile.py | 15 +- tools/gyp/gyp/MSVS/MSVSVersion.py | 365 ++ tools/gyp/gyp/MSVS/__init__.py | 507 ++ tools/gyp/gyp/Makefile.tmpl | 223 + .../make.py => gyp/MakefileWriter.py} | 1347 +----- tools/gyp/gyp/NinjaWriter.py | 1407 ++++++ tools/gyp/gyp/XCodeDetect.py | 65 + tools/gyp/{pylib => }/gyp/__init__.py | 245 +- .../buildtime_helpers}/flock_tool.py | 17 +- .../buildtime_helpers}/large-pdb-shim.cc | 0 .../gyp => gyp/buildtime_helpers}/mac_tool.py | 37 +- .../gyp => gyp/buildtime_helpers}/win_tool.py | 74 +- tools/gyp/{pylib => }/gyp/common.py | 156 +- tools/gyp/{pylib => }/gyp/easy_xml.py | 33 +- .../gyp/{pylib => }/gyp/generator/__init__.py | 0 .../gyp/{pylib => }/gyp/generator/analyzer.py | 105 +- tools/gyp/{pylib => }/gyp/generator/cmake.py | 185 +- .../gyp/generator/dump_dependency_json.py | 20 +- .../gyp/{pylib => }/gyp/generator/eclipse.py | 89 +- tools/gyp/{pylib => }/gyp/generator/gypd.py | 9 +- tools/gyp/{pylib => }/gyp/generator/gypsh.py | 10 +- tools/gyp/gyp/generator/make.py | 557 +++ tools/gyp/{pylib => }/gyp/generator/msvs.py | 995 ++-- tools/gyp/gyp/generator/ninja.py | 806 ++++ tools/gyp/{pylib => }/gyp/generator/xcode.py | 118 +- .../gyp => gyp/generator}/xcode_ninja.py | 8 +- .../gyp => gyp/generator}/xcodeproj_file.py | 107 +- tools/gyp/{pylib => }/gyp/input.py | 1011 ++-- tools/gyp/gyp/lib/__init__.py | 0 .../{pylib/gyp => gyp/lib}/ninja_syntax.py | 0 .../gyp/{pylib/gyp => gyp/lib}/simple_copy.py | 29 +- tools/gyp/{pylib => }/gyp/msvs_emulation.py | 626 ++- .../unit_tests}/MSVSSettings_test.py | 557 +-- tools/gyp/gyp/unit_tests/NinjaWriter_test.py | 39 + tools/gyp/gyp/unit_tests/__init__.py | 0 .../gyp => gyp/unit_tests}/common_test.py | 1 + .../gyp => gyp/unit_tests}/easy_xml_test.py | 4 +- .../unit_tests/generator_msvs_test.py} | 4 +- .../unit_tests/generator_xcode_test.py} | 0 .../gyp => gyp/unit_tests}/input_test.py | 23 +- tools/gyp/{pylib => }/gyp/xcode_emulation.py | 134 +- tools/gyp/gyp_main.py | 10 - tools/gyp/gyptest.py | 192 +- tools/gyp/pylib/gyp/MSVSProject.py | 208 - tools/gyp/pylib/gyp/MSVSUserFile.py | 147 - tools/gyp/pylib/gyp/MSVSUtil.py | 271 -- tools/gyp/pylib/gyp/MSVSVersion.py | 491 -- .../gyp/generator/compile_commands_json.py | 115 - tools/gyp/pylib/gyp/generator/ninja.py | 2488 ---------- tools/gyp/pylib/gyp/generator/ninja_test.py | 47 - tools/gyp/pylib/gyp/ordered_dict.py | 289 -- tools/gyp/pylib/gyp/xml_fix.py | 69 - tools/gyp/samples/samples | 81 - tools/gyp/samples/samples.bat | 5 - tools/gyp/setup.cfg | 14 + tools/gyp/setup.py | 19 - tools/gyp/test/actions/bare/gyptest-bare.py | 24 + tools/gyp/test/actions/bare/src/bare.gyp | 25 + tools/gyp/test/actions/bare/src/bare.py | 11 + tools/gyp/test/actions/depfile/depfile.gyp | 25 + tools/gyp/test/actions/depfile/gyptest-all.py | 20 + tools/gyp/test/actions/depfile/input.txt | 1 + .../actions/e2e/generated-header/action.py | 10 + .../test/actions/e2e/generated-header/main.cc | 7 + .../actions/e2e/generated-header/test.gyp | 34 + tools/gyp/test/actions/e2e/gyptest-all.py | 101 + tools/gyp/test/actions/e2e/gyptest-default.py | 68 + tools/gyp/test/actions/e2e/gyptest-errors.py | 24 + .../actions/e2e/gyptest-generated-header.py | 38 + .../actions/e2e/src/action_missing_name.gyp | 24 + tools/gyp/test/actions/e2e/src/actions.gyp | 114 + .../test/actions/e2e/src/confirm-dep-files.py | 21 + .../test/actions/e2e/src/subdir1/counter.py | 44 + .../actions/e2e/src/subdir1/executable.gyp | 74 + .../actions/e2e/src/subdir1/make-prog1.py | 20 + .../actions/e2e/src/subdir1/make-prog2.py | 20 + .../test/actions/e2e/src/subdir1/program.c | 12 + .../test/actions/e2e/src/subdir2/make-file.py | 11 + .../gyp/test/actions/e2e/src/subdir2/none.gyp | 33 + .../actions/e2e/src/subdir3/generate_main.py | 21 + .../actions/e2e/src/subdir3/null_input.gyp | 29 + .../gyptest-action.py | 45 + .../src/action.gyp | 28 + .../src/rcopy.py | 19 + .../gyptest-multiple-outputs.py | 45 + .../multiple-outputs/src/multiple-outputs.gyp | 23 + .../actions/multiple-outputs/src/touch.py | 16 + .../gyp/test/actions/multiple/gyptest-all.py | 72 + .../gyp/test/actions/multiple/src/actions.gyp | 226 + .../gyp/test/actions/multiple/src/copyfile.py | 9 + tools/gyp/test/actions/multiple/src/filter.py | 12 + tools/gyp/test/actions/multiple/src/foo.c | 11 + tools/gyp/test/actions/multiple/src/input.txt | 1 + tools/gyp/test/actions/multiple/src/main.c | 22 + tools/gyp/test/actions/none/gyptest-none.py | 24 + tools/gyp/test/actions/none/src/fake_cross.py | 12 + tools/gyp/test/actions/none/src/foo.cc | 1 + .../none/src/none_with_source_files.gyp | 35 + .../gyp/test/actions/subdir/gyptest-action.py | 26 + .../gyp/test/actions/subdir/src/make-file.py | 11 + tools/gyp/test/actions/subdir/src/none.gyp | 31 + .../subdir/src/subdir/make-subdir-file.py | 11 + .../test/actions/subdir/src/subdir/subdir.gyp | 28 + .../additional-targets/gyptest-additional.py | 63 + tools/gyp/test/additional-targets/src/all.gyp | 13 + .../additional-targets/src/dir1/actions.gyp | 56 + .../test/additional-targets/src/dir1/emit.py | 11 + .../test/additional-targets/src/dir1/lib1.c | 6 + tools/gyp/test/analyzer/common.gypi | 6 + tools/gyp/test/analyzer/gyptest-analyzer.py | 402 ++ .../gyp/test/analyzer/static_library_test.gyp | 34 + tools/gyp/test/analyzer/subdir/subdir.gyp | 36 + .../test/analyzer/subdir/subdir2/subdir2.gyp | 15 + tools/gyp/test/analyzer/subdir2/subdir.gyp | 18 + .../analyzer/subdir2/subdir.includes.gypi | 9 + tools/gyp/test/analyzer/test.gyp | 114 + tools/gyp/test/analyzer/test2.gyp | 25 + tools/gyp/test/analyzer/test2.includes.gypi | 13 + .../analyzer/test2.includes.includes.gypi | 9 + .../analyzer/test2.toplevel_includes.gypi | 15 + tools/gyp/test/analyzer/test3.gyp | 77 + tools/gyp/test/analyzer/test4.gyp | 80 + tools/gyp/test/analyzer/test5.gyp | 25 + tools/gyp/test/arflags/gyptest-arflags.py | 26 + tools/gyp/test/arflags/lib.cc | 0 tools/gyp/test/arflags/test.gyp | 10 + tools/gyp/test/assembly/gyptest-assembly.py | 31 + tools/gyp/test/assembly/gyptest-override.py | 24 + tools/gyp/test/assembly/src/as.bat | 4 + tools/gyp/test/assembly/src/assembly.gyp | 62 + tools/gyp/test/assembly/src/lib1.S | 15 + tools/gyp/test/assembly/src/lib1.c | 3 + tools/gyp/test/assembly/src/override.gyp | 34 + tools/gyp/test/assembly/src/override_asm.asm | 8 + tools/gyp/test/assembly/src/program.c | 12 + tools/gyp/test/build-option/gyptest-build.py | 24 + tools/gyp/test/build-option/hello.c | 13 + tools/gyp/test/build-option/hello.gyp | 15 + tools/gyp/test/builddir/gyptest-all.py | 85 + tools/gyp/test/builddir/gyptest-default.py | 85 + tools/gyp/test/builddir/src/builddir.gypi | 18 + tools/gyp/test/builddir/src/func1.c | 6 + tools/gyp/test/builddir/src/func2.c | 6 + tools/gyp/test/builddir/src/func3.c | 6 + tools/gyp/test/builddir/src/func4.c | 6 + tools/gyp/test/builddir/src/func5.c | 6 + tools/gyp/test/builddir/src/prog1.c | 10 + tools/gyp/test/builddir/src/prog1.gyp | 30 + tools/gyp/test/builddir/src/subdir2/prog2.c | 10 + tools/gyp/test/builddir/src/subdir2/prog2.gyp | 19 + .../test/builddir/src/subdir2/subdir3/prog3.c | 10 + .../builddir/src/subdir2/subdir3/prog3.gyp | 19 + .../src/subdir2/subdir3/subdir4/prog4.c | 10 + .../src/subdir2/subdir3/subdir4/prog4.gyp | 19 + .../subdir2/subdir3/subdir4/subdir5/prog5.c | 10 + .../subdir2/subdir3/subdir4/subdir5/prog5.gyp | 19 + tools/gyp/test/cflags/cflags.c | 15 + tools/gyp/test/cflags/cflags.gyp | 23 + tools/gyp/test/cflags/gyptest-cflags.py | 75 + tools/gyp/test/compilable/gyptest-headers.py | 29 + tools/gyp/test/compilable/src/headers.gyp | 26 + tools/gyp/test/compilable/src/lib1.cpp | 7 + tools/gyp/test/compilable/src/lib1.hpp | 6 + tools/gyp/test/compilable/src/program.cpp | 9 + .../test/compiler-override/compiler-exe.gyp | 16 + .../compiler-global-settings.gyp.in | 34 + .../test/compiler-override/compiler-host.gyp | 17 + .../compiler-override/compiler-shared-lib.gyp | 16 + tools/gyp/test/compiler-override/cxxtest.cc | 7 + .../gyptest-compiler-env-toolchain.py | 78 + .../compiler-override/gyptest-compiler-env.py | 110 + .../gyptest-compiler-global-settings.py | 82 + tools/gyp/test/compiler-override/my_cc.py | 7 + tools/gyp/test/compiler-override/my_cxx.py | 7 + tools/gyp/test/compiler-override/my_ld.py | 7 + tools/gyp/test/compiler-override/my_nm.py | 9 + .../gyp/test/compiler-override/my_readelf.py | 9 + tools/gyp/test/compiler-override/test.c | 7 + tools/gyp/test/conditions/elseif/elseif.gyp | 43 + .../test/conditions/elseif/elseif_bad1.gyp | 20 + .../test/conditions/elseif/elseif_bad2.gyp | 22 + .../test/conditions/elseif/elseif_bad3.gyp | 23 + .../conditions/elseif/elseif_conditions.gypi | 15 + .../test/conditions/elseif/gyptest_elseif.py | 33 + tools/gyp/test/conditions/elseif/program.cc | 10 + .../configurations/basics/configurations.c | 15 + .../configurations/basics/configurations.gyp | 32 + .../basics/gyptest-configurations.py | 29 + .../inheritance/configurations.c | 21 + .../inheritance/configurations.gyp | 40 + .../configurations/inheritance/duplicates.gyp | 27 + .../inheritance/duplicates.gypd.golden | 12 + .../inheritance/gyptest-duplicates.py | 36 + .../inheritance/gyptest-inheritance.py | 33 + .../test/configurations/invalid/actions.gyp | 18 + .../invalid/all_dependent_settings.gyp | 18 + .../configurations/invalid/configurations.gyp | 18 + .../configurations/invalid/dependencies.gyp | 18 + .../invalid/direct_dependent_settings.gyp | 18 + .../invalid/gyptest-configurations.py | 36 + .../test/configurations/invalid/libraries.gyp | 18 + .../configurations/invalid/link_settings.gyp | 18 + .../test/configurations/invalid/sources.gyp | 18 + .../invalid/standalone_static_library.gyp | 17 + .../configurations/invalid/target_name.gyp | 18 + .../gyp/test/configurations/invalid/type.gyp | 18 + .../target_platform/configurations.gyp | 58 + .../configurations/target_platform/front.c | 8 + .../gyptest-target_platform.py | 39 + .../configurations/target_platform/left.c | 3 + .../configurations/target_platform/right.c | 3 + .../test/configurations/x64/configurations.c | 12 + .../configurations/x64/configurations.gyp | 38 + .../test/configurations/x64/gyptest-x86.py | 29 + tools/gyp/test/copies/gyptest-all.py | 42 + tools/gyp/test/copies/gyptest-attribs.py | 39 + tools/gyp/test/copies/gyptest-default.py | 42 + tools/gyp/test/copies/gyptest-samedir.py | 28 + tools/gyp/test/copies/gyptest-slash.py | 39 + .../copies/gyptest-sourceless-shared-lib.py | 20 + tools/gyp/test/copies/gyptest-updir.py | 32 + tools/gyp/test/copies/src/copies-attribs.gyp | 20 + tools/gyp/test/copies/src/copies-samedir.gyp | 37 + tools/gyp/test/copies/src/copies-slash.gyp | 36 + .../src/copies-sourceless-shared-lib.gyp | 27 + tools/gyp/test/copies/src/copies-updir.gyp | 21 + tools/gyp/test/copies/src/copies.gyp | 70 + tools/gyp/test/copies/src/directory/file3 | 1 + tools/gyp/test/copies/src/directory/file4 | 1 + .../test/copies/src/directory/subdir/file5 | 1 + tools/gyp/test/copies/src/executable-file.sh | 3 + tools/gyp/test/copies/src/file1 | 1 + tools/gyp/test/copies/src/file2 | 1 + tools/gyp/test/copies/src/foo.c | 13 + .../test/copies/src/parentdir/subdir/file6 | 1 + .../gyptest-custom-generator.py | 18 + .../gyp/test/custom-generator/mygenerator.py | 14 + tools/gyp/test/custom-generator/test.gyp | 15 + tools/gyp/test/cxxflags/cxxflags.cc | 15 + tools/gyp/test/cxxflags/cxxflags.gyp | 15 + tools/gyp/test/cxxflags/gyptest-cxxflags.py | 45 + .../test/defines-escaping/defines-escaping.c | 11 + .../defines-escaping/defines-escaping.gyp | 19 + .../gyptest-defines-escaping.py | 184 + tools/gyp/test/defines/defines-env.gyp | 22 + tools/gyp/test/defines/defines.c | 23 + tools/gyp/test/defines/defines.gyp | 38 + .../test/defines/gyptest-define-override.py | 42 + .../test/defines/gyptest-defines-env-regyp.py | 51 + tools/gyp/test/defines/gyptest-defines-env.py | 85 + tools/gyp/test/defines/gyptest-defines.py | 39 + tools/gyp/test/dependencies/a.c | 9 + .../adso/all_dependent_settings_order.gyp | 45 + .../gyp/test/dependencies/adso/write_args.py | 11 + tools/gyp/test/dependencies/b/b.c | 3 + tools/gyp/test/dependencies/b/b.gyp | 22 + tools/gyp/test/dependencies/b/b3.c | 9 + tools/gyp/test/dependencies/c/c.c | 4 + tools/gyp/test/dependencies/c/c.gyp | 22 + tools/gyp/test/dependencies/c/d.c | 3 + .../test/dependencies/double_dependency.gyp | 23 + .../test/dependencies/double_dependent.gyp | 12 + tools/gyp/test/dependencies/extra_targets.gyp | 18 + .../gyptest-all-dependent-settings-order.py | 19 + .../dependencies/gyptest-double-dependency.py | 19 + .../dependencies/gyptest-extra-targets.py | 22 + .../gyptest-indirect-module-dependency.py | 22 + .../gyp/test/dependencies/gyptest-lib-only.py | 39 + .../dependencies/gyptest-none-traversal.py | 25 + .../gyptest-sharedlib-linksettings.py | 21 + tools/gyp/test/dependencies/lib_only.gyp | 16 + tools/gyp/test/dependencies/main.c | 14 + tools/gyp/test/dependencies/module-dep/a.cc | 7 + tools/gyp/test/dependencies/module-dep/dll.cc | 9 + tools/gyp/test/dependencies/module-dep/exe.cc | 7 + .../module-dep/indirect-module-dependency.gyp | 37 + .../gyp/test/dependencies/none_traversal.gyp | 46 + .../sharedlib-linksettings/program.c | 25 + .../sharedlib-linksettings/sharedlib.c | 16 + .../sharedlib-linksettings/staticlib.c | 24 + .../sharedlib-linksettings/test.gyp | 37 + .../gyp/test/dependency-copy/gyptest-copy.py | 26 + tools/gyp/test/dependency-copy/src/copies.gyp | 25 + tools/gyp/test/dependency-copy/src/file1.c | 7 + tools/gyp/test/dependency-copy/src/file2.c | 7 + tools/gyp/test/determinism/determinism.gyp | 59 + tools/gyp/test/determinism/empty-targets.gyp | 32 + .../test/determinism/gyptest-determinism.py | 30 + .../determinism/gyptest-empty-target-names.py | 30 + .../determinism/gyptest-needed-variables.py | 30 + tools/gyp/test/determinism/gyptest-solibs.py | 37 + tools/gyp/test/determinism/main.cc | 5 + .../gyp/test/determinism/needed-variables.gyp | 33 + tools/gyp/test/determinism/rule.py | 8 + tools/gyp/test/determinism/solib.cc | 8 + tools/gyp/test/determinism/solibs.gyp | 32 + tools/gyp/test/empty-target/empty-target.gyp | 12 + .../test/empty-target/gyptest-empty-target.py | 18 + tools/gyp/test/errors/dependency_cycle.gyp | 23 + tools/gyp/test/errors/duplicate_basenames.gyp | 13 + tools/gyp/test/errors/duplicate_node.gyp | 12 + tools/gyp/test/errors/duplicate_rule.gyp | 22 + tools/gyp/test/errors/duplicate_targets.gyp | 14 + tools/gyp/test/errors/error_command.gyp | 12 + tools/gyp/test/errors/file_cycle0.gyp | 17 + tools/gyp/test/errors/file_cycle1.gyp | 13 + tools/gyp/test/errors/gyptest-errors.py | 54 + tools/gyp/test/errors/missing_command.gyp | 12 + tools/gyp/test/errors/missing_dep.gyp | 15 + tools/gyp/test/errors/missing_targets.gyp | 8 + tools/gyp/test/escaping/colon/test.gyp | 21 + tools/gyp/test/escaping/gyptest-colon.py | 51 + tools/gyp/test/exclusion/exclusion.gyp | 23 + tools/gyp/test/exclusion/gyptest-exclusion.py | 22 + tools/gyp/test/exclusion/hello.c | 15 + .../external-cross-compile/gyptest-cross.py | 31 + .../test/external-cross-compile/src/bogus1.cc | 1 + .../test/external-cross-compile/src/bogus2.c | 1 + .../test/external-cross-compile/src/cross.gyp | 83 + .../src/cross_compile.gypi | 23 + .../external-cross-compile/src/fake_cross.py | 18 + .../external-cross-compile/src/program.cc | 16 + .../test/external-cross-compile/src/test1.cc | 1 + .../test/external-cross-compile/src/test2.c | 1 + .../test/external-cross-compile/src/test3.cc | 1 + .../test/external-cross-compile/src/test4.c | 1 + .../test/external-cross-compile/src/tochar.py | 13 + tools/gyp/test/fixtures/test-charmap.py | 22 + .../test/generator-output/actions/actions.gyp | 16 + .../generator-output/actions/build/README.txt | 4 + .../actions/subdir1/actions-out/README.txt | 4 + .../actions/subdir1/build/README.txt | 4 + .../actions/subdir1/executable.gyp | 44 + .../actions/subdir1/make-prog1.py | 20 + .../actions/subdir1/make-prog2.py | 20 + .../actions/subdir1/program.c | 12 + .../actions/subdir2/actions-out/README.txt | 4 + .../actions/subdir2/build/README.txt | 4 + .../actions/subdir2/make-file.py | 11 + .../generator-output/actions/subdir2/none.gyp | 31 + .../generator-output/copies/build/README.txt | 4 + .../copies/copies-out/README.txt | 4 + .../test/generator-output/copies/copies.gyp | 50 + tools/gyp/test/generator-output/copies/file1 | 1 + tools/gyp/test/generator-output/copies/file2 | 1 + .../copies/subdir/build/README.txt | 4 + .../copies/subdir/copies-out/README.txt | 4 + .../test/generator-output/copies/subdir/file3 | 1 + .../test/generator-output/copies/subdir/file4 | 1 + .../generator-output/copies/subdir/subdir.gyp | 32 + .../test/generator-output/gyptest-actions.py | 57 + .../test/generator-output/gyptest-copies.py | 59 + .../test/generator-output/gyptest-depth.py | 58 + .../generator-output/gyptest-mac-bundle.py | 33 + .../test/generator-output/gyptest-relocate.py | 59 + .../test/generator-output/gyptest-rules.py | 58 + .../generator-output/gyptest-subdir2-deep.py | 36 + .../test/generator-output/gyptest-symlink.py | 44 + .../test/generator-output/gyptest-top-all.py | 53 + .../generator-output/mac-bundle/Info.plist | 32 + .../generator-output/mac-bundle/app.order | 1 + .../test/generator-output/mac-bundle/header.h | 1 + .../test/generator-output/mac-bundle/main.c | 1 + .../generator-output/mac-bundle/resource.sb | 1 + .../test/generator-output/mac-bundle/test.gyp | 25 + .../generator-output/rules/build/README.txt | 4 + .../test/generator-output/rules/copy-file.py | 12 + .../gyp/test/generator-output/rules/rules.gyp | 16 + .../rules/subdir1/build/README.txt | 4 + .../rules/subdir1/define3.in0 | 1 + .../rules/subdir1/define4.in0 | 1 + .../rules/subdir1/executable.gyp | 59 + .../rules/subdir1/function1.in1 | 6 + .../rules/subdir1/function2.in1 | 6 + .../generator-output/rules/subdir1/program.c | 18 + .../rules/subdir2/build/README.txt | 4 + .../generator-output/rules/subdir2/file1.in0 | 1 + .../generator-output/rules/subdir2/file2.in0 | 1 + .../generator-output/rules/subdir2/file3.in1 | 1 + .../generator-output/rules/subdir2/file4.in1 | 1 + .../generator-output/rules/subdir2/none.gyp | 49 + .../rules/subdir2/rules-out/README.txt | 4 + .../generator-output/src/build/README.txt | 4 + tools/gyp/test/generator-output/src/inc.h | 1 + .../test/generator-output/src/inc1/include1.h | 1 + tools/gyp/test/generator-output/src/prog1.c | 18 + tools/gyp/test/generator-output/src/prog1.gyp | 28 + .../src/subdir2/build/README.txt | 4 + .../src/subdir2/deeper/build/README.txt | 4 + .../src/subdir2/deeper/deeper.c | 7 + .../src/subdir2/deeper/deeper.gyp | 18 + .../src/subdir2/deeper/deeper.h | 1 + .../src/subdir2/inc2/include2.h | 1 + .../test/generator-output/src/subdir2/prog2.c | 18 + .../generator-output/src/subdir2/prog2.gyp | 28 + .../src/subdir3/build/README.txt | 4 + .../src/subdir3/inc3/include3.h | 1 + .../test/generator-output/src/subdir3/prog3.c | 18 + .../generator-output/src/subdir3/prog3.gyp | 25 + .../test/generator-output/src/symroot.gypi | 16 + tools/gyp/test/gyp-defines/defines.gyp | 26 + tools/gyp/test/gyp-defines/echo.py | 11 + .../gyp-defines/gyptest-multiple-values.py | 36 + tools/gyp/test/gyp-defines/gyptest-regyp.py | 40 + .../gyptest-exported-hard-dependency.py | 37 + .../gyptest-no-exported-hard-dependency.py | 36 + tools/gyp/test/hard_dependency/src/a.c | 9 + tools/gyp/test/hard_dependency/src/a.h | 12 + tools/gyp/test/hard_dependency/src/b.c | 9 + tools/gyp/test/hard_dependency/src/b.h | 12 + tools/gyp/test/hard_dependency/src/c.c | 10 + tools/gyp/test/hard_dependency/src/c.h | 10 + tools/gyp/test/hard_dependency/src/d.c | 9 + tools/gyp/test/hard_dependency/src/emit.py | 11 + .../hard_dependency/src/hard_dependency.gyp | 78 + tools/gyp/test/hello/gyptest-all.py | 24 + tools/gyp/test/hello/gyptest-default.py | 24 + tools/gyp/test/hello/gyptest-disable-regyp.py | 32 + tools/gyp/test/hello/gyptest-regyp-output.py | 36 + tools/gyp/test/hello/gyptest-regyp.py | 32 + tools/gyp/test/hello/gyptest-target.py | 24 + tools/gyp/test/hello/hello.c | 11 + tools/gyp/test/hello/hello.gyp | 15 + tools/gyp/test/hello/hello2.c | 11 + tools/gyp/test/hello/hello2.gyp | 15 + .../gyptest-home-includes-config-arg.py | 31 + .../gyptest-home-includes-config-env.py | 33 + .../gyptest-home-includes-regyp.py | 44 + .../home_dot_gyp/gyptest-home-includes.py | 30 + tools/gyp/test/home_dot_gyp/src/all.gyp | 22 + tools/gyp/test/home_dot_gyp/src/printfoo.c | 7 + tools/gyp/test/include_dirs/gyptest-all.py | 43 + .../gyp/test/include_dirs/gyptest-default.py | 43 + tools/gyp/test/include_dirs/src/inc.h | 1 + .../gyp/test/include_dirs/src/inc1/include1.h | 1 + tools/gyp/test/include_dirs/src/includes.c | 19 + tools/gyp/test/include_dirs/src/includes.gyp | 27 + .../test/include_dirs/src/shadow1/shadow.h | 1 + .../test/include_dirs/src/shadow2/shadow.h | 1 + tools/gyp/test/include_dirs/src/subdir/inc.h | 1 + .../include_dirs/src/subdir/inc2/include2.h | 1 + .../include_dirs/src/subdir/subdir_includes.c | 14 + .../src/subdir/subdir_includes.gyp | 20 + .../gyptest-intermediate-dir.py | 44 + tools/gyp/test/intermediate_dir/src/script.py | 22 + .../intermediate_dir/src/shared_infile.txt | 1 + tools/gyp/test/intermediate_dir/src/test.gyp | 42 + tools/gyp/test/intermediate_dir/src/test2.gyp | 42 + .../English.lproj/InfoPlist-error.strings | 3 + .../TestApp/English.lproj/InfoPlist.strings | 3 + .../TestApp/English.lproj/LanguageMap.plist | 8 + .../TestApp/English.lproj/MainMenu.xib | 17 + .../English.lproj/Main_iPhone.storyboard | 27 + .../AppIcon.appiconset/Contents.json | 58 + .../image.imageset/Contents.json | 23 + .../image.imageset/super_sylvain.png | Bin 0 -> 3263 bytes .../image.imageset/super_sylvain@2x.png | Bin 0 -> 3847 bytes .../image.imageset/super_sylvain@3x.png | Bin 0 -> 4394 bytes .../ios/app-bundle/TestApp/TestApp-Info.plist | 28 + .../app-bundle/TestApp/check_no_signature.py | 13 + tools/gyp/test/ios/app-bundle/TestApp/main.m | 13 + .../TestApp/only-compile-in-32-bits.m | 7 + .../TestApp/only-compile-in-64-bits.m | 7 + tools/gyp/test/ios/app-bundle/test-archs.gyp | 109 + .../ios/app-bundle/test-assets-catalog.gyp | 45 + .../test/ios/app-bundle/test-crosscompile.gyp | 47 + tools/gyp/test/ios/app-bundle/test-device.gyp | 109 + tools/gyp/test/ios/app-bundle/test.gyp | 75 + tools/gyp/test/ios/app-bundle/tool_main.cc | 7 + .../ios/copies-with-xcode-envvars/Info.plist | 24 + .../copies-with-xcode-envvars.gyp | 97 + .../ios/copies-with-xcode-envvars/empty.c | 1 + .../test/ios/copies-with-xcode-envvars/file0 | 1 + .../test/ios/copies-with-xcode-envvars/file1 | 1 + .../test/ios/copies-with-xcode-envvars/file10 | 1 + .../test/ios/copies-with-xcode-envvars/file11 | 1 + .../test/ios/copies-with-xcode-envvars/file2 | 1 + .../test/ios/copies-with-xcode-envvars/file3 | 1 + .../test/ios/copies-with-xcode-envvars/file4 | 1 + .../test/ios/copies-with-xcode-envvars/file5 | 1 + .../test/ios/copies-with-xcode-envvars/file6 | 1 + .../test/ios/copies-with-xcode-envvars/file7 | 1 + .../test/ios/copies-with-xcode-envvars/file8 | 1 + .../test/ios/copies-with-xcode-envvars/file9 | 1 + .../ios/deployment-target/check-version-min.c | 33 + .../deployment-target/deployment-target.gyp | 34 + .../ActionExtension/ActionViewController.h | 9 + .../ActionExtension/ActionViewController.m | 31 + .../ios/extension/ActionExtension/Info.plist | 42 + .../ActionExtension/MainInterface.storyboard | 63 + .../ExtensionContainer/AppDelegate.h | 12 + .../ExtensionContainer/AppDelegate.m | 19 + .../Base.lproj/Main.storyboard | 25 + .../AppIcon.appiconset/Contents.json | 53 + .../LaunchImage.launchimage/Contents.json | 51 + .../extension/ExtensionContainer/Info.plist | 32 + .../ExtensionContainer/ViewController.h | 11 + .../ExtensionContainer/ViewController.m | 24 + .../ios/extension/ExtensionContainer/main.m | 13 + tools/gyp/test/ios/extension/extension.gyp | 91 + tools/gyp/test/ios/framework/framework.gyp | 43 + .../ios/framework/iOSFramework/Info.plist | 26 + .../test/ios/framework/iOSFramework/Thing.h | 10 + .../test/ios/framework/iOSFramework/Thing.m | 22 + .../ios/framework/iOSFramework/iOSFramework.h | 9 + .../ios/gyptest-app-ios-assets-catalog.py | 37 + tools/gyp/test/ios/gyptest-app-ios.py | 62 + tools/gyp/test/ios/gyptest-archs.py | 59 + .../ios/gyptest-copies-with-xcode-envvars.py | 54 + tools/gyp/test/ios/gyptest-crosscompile.py | 18 + .../gyp/test/ios/gyptest-deployment-target.py | 24 + tools/gyp/test/ios/gyptest-extension.py | 52 + tools/gyp/test/ios/gyptest-framework.py | 24 + .../test/ios/gyptest-per-config-settings.py | 185 + tools/gyp/test/ios/gyptest-watch.py | 25 + tools/gyp/test/ios/gyptest-xcode-ninja.py | 25 + .../AppIcon.appiconset/Contents.json | 62 + .../LaunchImage.launchimage/Contents.json | 24 + tools/gyp/test/ios/watch/WatchApp/Info.plist | 35 + .../ios/watch/WatchApp/Interface.storyboard | 15 + .../ios/watch/WatchContainer/AppDelegate.h | 12 + .../ios/watch/WatchContainer/AppDelegate.m | 19 + .../WatchContainer/Base.lproj/Main.storyboard | 25 + .../AppIcon.appiconset/Contents.json | 53 + .../LaunchImage.launchimage/Contents.json | 51 + .../test/ios/watch/WatchContainer/Info.plist | 32 + .../ios/watch/WatchContainer/ViewController.h | 11 + .../ios/watch/WatchContainer/ViewController.m | 24 + .../gyp/test/ios/watch/WatchContainer/main.m | 13 + .../MyImage.imageset/Contents.json | 20 + .../ios/watch/WatchKitExtension/Info.plist | 38 + .../WatchKitExtension/InterfaceController.h | 10 + .../WatchKitExtension/InterfaceController.m | 25 + .../MainInterface.storyboard | 63 + tools/gyp/test/ios/watch/watch.gyp | 105 + tools/gyp/test/ios/xctests/App/AppDelegate.h | 11 + tools/gyp/test/ios/xctests/App/AppDelegate.m | 18 + .../xctests/App/Base.lproj/LaunchScreen.xib | 41 + .../xctests/App/Base.lproj/Main.storyboard | 25 + .../AppIcon.appiconset/Contents.json | 68 + tools/gyp/test/ios/xctests/App/Info.plist | 47 + .../gyp/test/ios/xctests/App/ViewController.h | 9 + .../gyp/test/ios/xctests/App/ViewController.m | 21 + tools/gyp/test/ios/xctests/App/main.m | 13 + .../gyp/test/ios/xctests/AppTests/AppTests.m | 31 + .../gyp/test/ios/xctests/AppTests/Info.plist | 24 + tools/gyp/test/ios/xctests/gyptest-xctests.py | 49 + tools/gyp/test/ios/xctests/xctests.gyp | 74 + .../gyptest-shared-obj-install-path.py | 39 + tools/gyp/test/library/gyptest-shared.py | 84 + tools/gyp/test/library/gyptest-static.py | 84 + tools/gyp/test/library/src/lib1.c | 10 + tools/gyp/test/library/src/lib1_moveable.c | 10 + tools/gyp/test/library/src/lib2.c | 10 + tools/gyp/test/library/src/lib2_moveable.c | 10 + tools/gyp/test/library/src/library.gyp | 58 + tools/gyp/test/library/src/program.c | 15 + .../test/library/src/shared_dependency.gyp | 33 + .../test/library_dirs/gyptest-library-dirs.py | 50 + tools/gyp/test/library_dirs/subdir/README.txt | 1 + tools/gyp/test/library_dirs/subdir/hello.cc | 11 + tools/gyp/test/library_dirs/subdir/mylib.cc | 9 + tools/gyp/test/library_dirs/subdir/mylib.h | 12 + .../gyp/test/library_dirs/subdir/test-win.gyp | 60 + tools/gyp/test/library_dirs/subdir/test.gyp | 68 + .../gyptest-link-dependency.py | 23 + tools/gyp/test/link-dependency/main.c | 7 + tools/gyp/test/link-dependency/mymalloc.c | 12 + tools/gyp/test/link-dependency/test.gyp | 37 + tools/gyp/test/link-objects/base.c | 6 + tools/gyp/test/link-objects/extra.c | 5 + tools/gyp/test/link-objects/gyptest-all.py | 28 + tools/gyp/test/link-objects/link-objects.gyp | 24 + .../gyp/test/linux/gyptest-implicit-rpath.py | 38 + .../test/linux/gyptest-ldflags-duplicates.py | 22 + .../linux/gyptest-ldflags-from-environment.py | 42 + tools/gyp/test/linux/gyptest-target-rpath.py | 35 + tools/gyp/test/linux/implicit-rpath/file.c | 1 + tools/gyp/test/linux/implicit-rpath/main.c | 1 + tools/gyp/test/linux/implicit-rpath/test.gyp | 47 + .../linux/ldflags-duplicates/check-ldflags.py | 28 + .../gyp/test/linux/ldflags-duplicates/lib1.c | 6 + .../gyp/test/linux/ldflags-duplicates/lib2.c | 6 + .../gyp/test/linux/ldflags-duplicates/main.c | 7 + .../test/linux/ldflags-duplicates/test.gyp | 45 + .../linux/ldflags-from-environment/main.c | 7 + .../linux/ldflags-from-environment/test.gyp | 23 + tools/gyp/test/linux/target-rpath/file.c | 1 + tools/gyp/test/linux/target-rpath/main.c | 1 + tools/gyp/test/linux/target-rpath/test.gyp | 47 + .../test/mac/action-envvars/action/action.gyp | 34 + .../test/mac/action-envvars/action/action.sh | 8 + .../English.lproj/InfoPlist-error.strings | 3 + .../TestApp/English.lproj/InfoPlist.strings | 3 + .../TestApp/English.lproj/MainMenu.xib | 4119 +++++++++++++++++ .../TestApp/English.lproj/utf-16be.strings | Bin 0 -> 208 bytes .../TestApp/English.lproj/utf-16le.strings | Bin 0 -> 208 bytes .../AppIcon.appiconset/Contents.json | 58 + .../image.imageset/Contents.json | 23 + .../image.imageset/super_sylvain.png | Bin 0 -> 3263 bytes .../image.imageset/super_sylvain@2x.png | Bin 0 -> 3847 bytes .../image.imageset/super_sylvain@3x.png | Bin 0 -> 4394 bytes .../mac/app-bundle/TestApp/TestApp-Info.plist | 34 + .../app-bundle/TestApp/TestAppAppDelegate.h | 13 + .../app-bundle/TestApp/TestAppAppDelegate.m | 15 + tools/gyp/test/mac/app-bundle/TestApp/main.m | 10 + tools/gyp/test/mac/app-bundle/empty.c | 0 .../mac/app-bundle/test-assets-catalog.gyp | 43 + tools/gyp/test/mac/app-bundle/test-error.gyp | 31 + tools/gyp/test/mac/app-bundle/test.gyp | 41 + tools/gyp/test/mac/archs/empty_main.cc | 1 + tools/gyp/test/mac/archs/file.mm | 1 + tools/gyp/test/mac/archs/file_a.cc | 8 + tools/gyp/test/mac/archs/file_a.h | 10 + tools/gyp/test/mac/archs/file_b.cc | 8 + tools/gyp/test/mac/archs/file_b.h | 10 + tools/gyp/test/mac/archs/file_c.cc | 11 + tools/gyp/test/mac/archs/file_d.cc | 11 + tools/gyp/test/mac/archs/header.h | 1 + tools/gyp/test/mac/archs/my_file.cc | 4 + tools/gyp/test/mac/archs/my_main_file.cc | 9 + .../test/mac/archs/test-archs-multiarch.gyp | 92 + .../gyp/test/mac/archs/test-archs-x86_64.gyp | 27 + .../gyp/test/mac/archs/test-dependencies.gyp | 92 + tools/gyp/test/mac/archs/test-no-archs.gyp | 21 + tools/gyp/test/mac/archs/test-valid-archs.gyp | 28 + tools/gyp/test/mac/bundle-resources/change.sh | 3 + .../mac/bundle-resources/executable-file.sh | 3 + .../gyp/test/mac/bundle-resources/secret.txt | 1 + tools/gyp/test/mac/bundle-resources/test.gyp | 59 + tools/gyp/test/mac/cflags/ccfile.cc | 7 + .../gyp/test/mac/cflags/ccfile_withcflags.cc | 7 + tools/gyp/test/mac/cflags/cfile.c | 7 + tools/gyp/test/mac/cflags/cppfile.cpp | 7 + .../test/mac/cflags/cppfile_withcflags.cpp | 7 + tools/gyp/test/mac/cflags/cxxfile.cxx | 7 + .../test/mac/cflags/cxxfile_withcflags.cxx | 7 + tools/gyp/test/mac/cflags/mfile.m | 7 + tools/gyp/test/mac/cflags/mmfile.mm | 7 + .../gyp/test/mac/cflags/mmfile_withcflags.mm | 7 + tools/gyp/test/mac/cflags/test.gyp | 132 + .../mac/clang-cxx-language-standard/c++11.cc | 8 + .../mac/clang-cxx-language-standard/c++98.cc | 24 + .../clang-cxx-language-standard.gyp | 30 + .../clang-cxx-library/clang-cxx-library.gyp | 32 + .../gyp/test/mac/clang-cxx-library/libc++.cc | 11 + .../test/mac/clang-cxx-library/libstdc++.cc | 11 + .../copies-with-xcode-envvars.gyp | 87 + .../mac/copies-with-xcode-envvars/empty.c | 1 + .../test/mac/copies-with-xcode-envvars/file0 | 1 + .../test/mac/copies-with-xcode-envvars/file1 | 1 + .../test/mac/copies-with-xcode-envvars/file10 | 1 + .../test/mac/copies-with-xcode-envvars/file11 | 1 + .../test/mac/copies-with-xcode-envvars/file2 | 1 + .../test/mac/copies-with-xcode-envvars/file3 | 1 + .../test/mac/copies-with-xcode-envvars/file4 | 1 + .../test/mac/copies-with-xcode-envvars/file5 | 1 + .../test/mac/copies-with-xcode-envvars/file6 | 1 + .../test/mac/copies-with-xcode-envvars/file7 | 1 + .../test/mac/copies-with-xcode-envvars/file8 | 1 + .../test/mac/copies-with-xcode-envvars/file9 | 1 + tools/gyp/test/mac/copy-dylib/empty.c | 1 + tools/gyp/test/mac/copy-dylib/test.gyp | 31 + tools/gyp/test/mac/debuginfo/file.c | 6 + tools/gyp/test/mac/debuginfo/test.gyp | 82 + .../English.lproj/InfoPlist.strings | 1 + .../gyp/test/mac/depend-on-bundle/Info.plist | 28 + tools/gyp/test/mac/depend-on-bundle/bundle.c | 1 + .../test/mac/depend-on-bundle/executable.c | 4 + tools/gyp/test/mac/depend-on-bundle/test.gyp | 28 + .../mac/deployment-target/check-version-min.c | 33 + .../deployment-target/deployment-target.gyp | 28 + tools/gyp/test/mac/framework-dirs/calculate.c | 15 + .../mac/framework-dirs/framework-dirs.gyp | 21 + .../test/mac/framework-headers/myframework.h | 8 + .../test/mac/framework-headers/myframework.m | 8 + tools/gyp/test/mac/framework-headers/test.gyp | 44 + .../English.lproj/InfoPlist.strings | 2 + .../mac/framework/TestFramework/Info.plist | 28 + .../mac/framework/TestFramework/ObjCVector.h | 28 + .../mac/framework/TestFramework/ObjCVector.mm | 63 + .../TestFramework/ObjCVectorInternal.h | 9 + .../TestFramework/TestFramework_Prefix.pch | 7 + tools/gyp/test/mac/framework/empty.c | 0 tools/gyp/test/mac/framework/framework.gyp | 108 + .../mac/global-settings/src/dir1/dir1.gyp | 11 + .../mac/global-settings/src/dir2/dir2.gyp | 22 + .../mac/global-settings/src/dir2/file.txt | 1 + tools/gyp/test/mac/gyptest-action-envvars.py | 36 + .../test/mac/gyptest-app-assets-catalog.py | 101 + tools/gyp/test/mac/gyptest-app-error.py | 56 + tools/gyp/test/mac/gyptest-app.py | 108 + tools/gyp/test/mac/gyptest-archs.py | 93 + .../gyp/test/mac/gyptest-bundle-resources.py | 63 + tools/gyp/test/mac/gyptest-cflags.py | 21 + .../gyptest-clang-cxx-language-standard.py | 25 + .../gyp/test/mac/gyptest-clang-cxx-library.py | 26 + .../mac/gyptest-copies-with-xcode-envvars.py | 54 + tools/gyp/test/mac/gyptest-copies.py | 61 + tools/gyp/test/mac/gyptest-copy-dylib.py | 25 + tools/gyp/test/mac/gyptest-debuginfo.py | 36 + .../gyp/test/mac/gyptest-depend-on-bundle.py | 45 + .../gyp/test/mac/gyptest-deployment-target.py | 27 + tools/gyp/test/mac/gyptest-framework-dirs.py | 23 + .../gyp/test/mac/gyptest-framework-headers.py | 38 + tools/gyp/test/mac/gyptest-framework.py | 77 + tools/gyp/test/mac/gyptest-global-settings.py | 33 + tools/gyp/test/mac/gyptest-identical-name.py | 42 + .../gyp/test/mac/gyptest-infoplist-process.py | 56 + tools/gyp/test/mac/gyptest-installname.py | 85 + tools/gyp/test/mac/gyptest-kext.py | 12 + .../mac/gyptest-ldflags-passed-to-libtool.py | 37 + tools/gyp/test/mac/gyptest-ldflags.py | 74 + tools/gyp/test/mac/gyptest-libraries.py | 30 + tools/gyp/test/mac/gyptest-libtool-zero.py | 26 + ...oadable-module-bundle-product-extension.py | 31 + tools/gyp/test/mac/gyptest-loadable-module.py | 51 + tools/gyp/test/mac/gyptest-lto.py | 66 + .../mac/gyptest-missing-cfbundlesignature.py | 34 + .../mac/gyptest-non-strs-flattened-to-env.py | 38 + tools/gyp/test/mac/gyptest-objc-arc.py | 26 + tools/gyp/test/mac/gyptest-objc-gc.py | 48 + .../test/mac/gyptest-postbuild-copy-bundle.py | 75 + .../test/mac/gyptest-postbuild-defaults.py | 34 + tools/gyp/test/mac/gyptest-postbuild-fail.py | 53 + ...ptest-postbuild-multiple-configurations.py | 26 + .../mac/gyptest-postbuild-static-library.py | 28 + tools/gyp/test/mac/gyptest-postbuild.py | 53 + tools/gyp/test/mac/gyptest-prefixheader.py | 20 + tools/gyp/test/mac/gyptest-rebuild.py | 46 + tools/gyp/test/mac/gyptest-rpath.py | 50 + tools/gyp/test/mac/gyptest-sdkroot.py | 56 + .../gyp/test/mac/gyptest-sourceless-module.py | 77 + tools/gyp/test/mac/gyptest-strip-default.py | 97 + tools/gyp/test/mac/gyptest-strip.py | 62 + tools/gyp/test/mac/gyptest-swift-library.py | 62 + tools/gyp/test/mac/gyptest-type-envvars.py | 25 + .../gyp/test/mac/gyptest-unicode-settings.py | 20 + tools/gyp/test/mac/gyptest-xcode-env-order.py | 85 + tools/gyp/test/mac/gyptest-xcode-gcc-clang.py | 39 + tools/gyp/test/mac/gyptest-xcode-gcc.py | 51 + .../test/mac/gyptest-xcode-support-actions.py | 25 + tools/gyp/test/mac/gyptest-xctest.py | 41 + tools/gyp/test/mac/gyptest-xcuitest.py | 39 + .../test/mac/identical-name/proxy/proxy.cc | 2 + .../test/mac/identical-name/proxy/proxy.gyp | 9 + .../identical-name/proxy/testlib/testlib.cc | 2 + .../identical-name/proxy/testlib/testlib.gyp | 8 + .../mac/identical-name/test-should-fail.gyp | 10 + tools/gyp/test/mac/identical-name/test.gyp | 11 + tools/gyp/test/mac/identical-name/test.gypi | 7 + .../test/mac/identical-name/testlib/main.cc | 3 + .../mac/identical-name/testlib/testlib.gyp | 14 + .../test/mac/identical-name/testlib/void.cc | 2 + .../gyp/test/mac/infoplist-process/Info.plist | 36 + tools/gyp/test/mac/infoplist-process/main.c | 7 + .../gyp/test/mac/infoplist-process/test1.gyp | 25 + .../gyp/test/mac/infoplist-process/test2.gyp | 25 + .../gyp/test/mac/infoplist-process/test3.gyp | 25 + tools/gyp/test/mac/installname/Info.plist | 28 + tools/gyp/test/mac/installname/file.c | 1 + tools/gyp/test/mac/installname/main.c | 1 + tools/gyp/test/mac/installname/test.gyp | 93 + .../test/mac/kext/GypKext/GypKext-Info.plist | 35 + tools/gyp/test/mac/kext/GypKext/GypKext.c | 16 + tools/gyp/test/mac/kext/kext.gyp | 18 + tools/gyp/test/mac/ldflags-libtool/file.c | 1 + tools/gyp/test/mac/ldflags-libtool/test.gyp | 17 + .../test/mac/ldflags/subdirectory/Info.plist | 8 + .../gyp/test/mac/ldflags/subdirectory/file.c | 2 + .../mac/ldflags/subdirectory/symbol_list.def | 1 + .../test/mac/ldflags/subdirectory/test.gyp | 66 + .../gyp/test/mac/libraries/subdir/README.txt | 1 + tools/gyp/test/mac/libraries/subdir/hello.cc | 10 + tools/gyp/test/mac/libraries/subdir/mylib.c | 7 + tools/gyp/test/mac/libraries/subdir/test.gyp | 65 + tools/gyp/test/mac/libtool-zero/mylib.c | 7 + tools/gyp/test/mac/libtool-zero/test.gyp | 18 + .../src.cc | 7 + .../test.gyp | 24 + tools/gyp/test/mac/loadable-module/Info.plist | 26 + tools/gyp/test/mac/loadable-module/module.c | 11 + tools/gyp/test/mac/loadable-module/test.gyp | 18 + tools/gyp/test/mac/lto/asmfile.S | 2 + tools/gyp/test/mac/lto/ccfile.cc | 1 + tools/gyp/test/mac/lto/cfile.c | 1 + tools/gyp/test/mac/lto/mfile.m | 1 + tools/gyp/test/mac/lto/mmfile.mm | 1 + tools/gyp/test/mac/lto/test.gyp | 35 + .../mac/missing-cfbundlesignature/Info.plist | 10 + .../Other-Info.plist | 12 + .../Third-Info.plist | 12 + .../test/mac/missing-cfbundlesignature/file.c | 1 + .../mac/missing-cfbundlesignature/test.gyp | 34 + .../mac/non-strs-flattened-to-env/Info.plist | 15 + .../test/mac/non-strs-flattened-to-env/main.c | 7 + .../mac/non-strs-flattened-to-env/test.gyp | 27 + tools/gyp/test/mac/objc-arc/c-file.c | 6 + tools/gyp/test/mac/objc-arc/cc-file.cc | 5 + tools/gyp/test/mac/objc-arc/m-file-no-arc.m | 5 + tools/gyp/test/mac/objc-arc/m-file.m | 5 + tools/gyp/test/mac/objc-arc/mm-file-no-arc.mm | 5 + tools/gyp/test/mac/objc-arc/mm-file.mm | 5 + tools/gyp/test/mac/objc-arc/test.gyp | 45 + tools/gyp/test/mac/objc-gc/c-file.c | 1 + tools/gyp/test/mac/objc-gc/cc-file.cc | 1 + tools/gyp/test/mac/objc-gc/main.m | 6 + tools/gyp/test/mac/objc-gc/needs-gc-mm.mm | 1 + tools/gyp/test/mac/objc-gc/needs-gc.m | 1 + tools/gyp/test/mac/objc-gc/test.gyp | 102 + .../Framework-Info.plist | 30 + .../postbuild-copy-bundle/TestApp-Info.plist | 32 + .../test/mac/postbuild-copy-bundle/copied.txt | 1 + .../test/mac/postbuild-copy-bundle/empty.c | 0 .../gyp/test/mac/postbuild-copy-bundle/main.c | 4 + .../postbuild-copy-framework.sh | 9 + .../postbuild-copy-bundle/resource_file.sb | 1 + .../test/mac/postbuild-copy-bundle/test.gyp | 49 + .../test/mac/postbuild-defaults/Info.plist | 13 + tools/gyp/test/mac/postbuild-defaults/main.c | 7 + .../postbuild-defaults/postbuild-defaults.sh | 15 + .../gyp/test/mac/postbuild-defaults/test.gyp | 26 + tools/gyp/test/mac/postbuild-fail/file.c | 6 + .../test/mac/postbuild-fail/postbuild-fail.sh | 6 + tools/gyp/test/mac/postbuild-fail/test.gyp | 38 + .../test/mac/postbuild-fail/touch-dynamic.sh | 7 + .../test/mac/postbuild-fail/touch-static.sh | 7 + .../postbuild-multiple-configurations/main.c | 4 + .../postbuild-touch-file.sh | 7 + .../test.gyp | 26 + .../test/mac/postbuild-static-library/empty.c | 4 + .../postbuild-touch-file.sh | 7 + .../mac/postbuild-static-library/test.gyp | 34 + tools/gyp/test/mac/postbuilds/copy.sh | 3 + tools/gyp/test/mac/postbuilds/file.c | 4 + tools/gyp/test/mac/postbuilds/file_g.c | 4 + tools/gyp/test/mac/postbuilds/file_h.c | 4 + .../script/shared_library_postbuild.sh | 23 + .../script/static_library_postbuild.sh | 23 + .../postbuilds/subdirectory/copied_file.txt | 1 + .../postbuilds/subdirectory/nested_target.gyp | 53 + tools/gyp/test/mac/postbuilds/test.gyp | 93 + tools/gyp/test/mac/prefixheader/file.c | 1 + tools/gyp/test/mac/prefixheader/file.cc | 1 + tools/gyp/test/mac/prefixheader/file.m | 1 + tools/gyp/test/mac/prefixheader/file.mm | 1 + tools/gyp/test/mac/prefixheader/header.h | 1 + tools/gyp/test/mac/prefixheader/test.gyp | 82 + tools/gyp/test/mac/rebuild/TestApp-Info.plist | 32 + tools/gyp/test/mac/rebuild/delay-touch.sh | 6 + tools/gyp/test/mac/rebuild/empty.c | 0 tools/gyp/test/mac/rebuild/main.c | 1 + tools/gyp/test/mac/rebuild/test.gyp | 56 + tools/gyp/test/mac/rpath/file.c | 1 + tools/gyp/test/mac/rpath/main.c | 1 + tools/gyp/test/mac/rpath/test.gyp | 48 + tools/gyp/test/mac/sdkroot/file.cc | 5 + tools/gyp/test/mac/sdkroot/test.gyp | 35 + tools/gyp/test/mac/sdkroot/test_shorthand.sh | 20 + tools/gyp/test/mac/sourceless-module/empty.c | 1 + .../gyp/test/mac/sourceless-module/empty.txt | 2 + tools/gyp/test/mac/sourceless-module/fun.c | 1 + tools/gyp/test/mac/sourceless-module/test.gyp | 96 + tools/gyp/test/mac/strip/file.c | 22 + tools/gyp/test/mac/strip/main.c | 25 + tools/gyp/test/mac/strip/strip.saves | 5 + .../test/mac/strip/subdirectory/nested_file.c | 1 + .../mac/strip/subdirectory/nested_strip.saves | 5 + .../mac/strip/subdirectory/subdirectory.gyp | 38 + .../test_reading_save_file_from_postbuild.sh | 5 + tools/gyp/test/mac/strip/test-defaults.gyp | 51 + tools/gyp/test/mac/strip/test.gyp | 119 + tools/gyp/test/mac/swift-library/Info.plist | 28 + tools/gyp/test/mac/swift-library/file.swift | 9 + tools/gyp/test/mac/swift-library/test.gyp | 21 + tools/gyp/test/mac/type_envvars/file.c | 6 + tools/gyp/test/mac/type_envvars/test.gyp | 100 + .../type_envvars/test_bundle_executable.sh | 30 + .../test_bundle_loadable_module.sh | 35 + .../test_bundle_shared_library.sh | 38 + .../mac/type_envvars/test_check_sdkroot.sh | 47 + .../type_envvars/test_nonbundle_executable.sh | 33 + .../test_nonbundle_loadable_module.sh | 31 + .../mac/type_envvars/test_nonbundle_none.sh | 32 + .../test_nonbundle_shared_library.sh | 31 + .../test_nonbundle_static_library.sh | 31 + tools/gyp/test/mac/unicode-settings/file.cc | 2 + tools/gyp/test/mac/unicode-settings/test.gyp | 23 + .../test_bundle_display_name.sh | 7 + tools/gyp/test/mac/xcode-env-order/Info.plist | 56 + tools/gyp/test/mac/xcode-env-order/file.ext1 | 0 tools/gyp/test/mac/xcode-env-order/file.ext2 | 0 tools/gyp/test/mac/xcode-env-order/file.ext3 | 0 tools/gyp/test/mac/xcode-env-order/main.c | 7 + tools/gyp/test/mac/xcode-env-order/test.gyp | 121 + tools/gyp/test/mac/xcode-gcc/aliasing.cc | 13 + tools/gyp/test/mac/xcode-gcc/test-clang.gyp | 42 + tools/gyp/test/mac/xcode-gcc/test.gyp | 60 + tools/gyp/test/mac/xcode-gcc/valid_c.c | 8 + tools/gyp/test/mac/xcode-gcc/valid_cc.cc | 8 + tools/gyp/test/mac/xcode-gcc/valid_m.m | 8 + tools/gyp/test/mac/xcode-gcc/valid_mm.mm | 8 + .../warn_about_invalid_offsetof_macro.cc | 15 + .../xcode-gcc/warn_about_missing_newline.c | 8 + .../test/mac/xcode-support-actions/source.c | 0 .../test/mac/xcode-support-actions/test.gyp | 26 + tools/gyp/test/mac/xctest/MyClass.h | 8 + tools/gyp/test/mac/xctest/MyClass.m | 8 + tools/gyp/test/mac/xctest/TestCase.m | 16 + tools/gyp/test/mac/xctest/resource.txt | 1 + tools/gyp/test/mac/xctest/test.gyp | 47 + tools/gyp/test/mac/xcuitest/Info.plist | 28 + tools/gyp/test/mac/xcuitest/MyAppDelegate.h | 8 + tools/gyp/test/mac/xcuitest/MyAppDelegate.m | 19 + tools/gyp/test/mac/xcuitest/TestCase.m | 15 + tools/gyp/test/mac/xcuitest/main.m | 15 + tools/gyp/test/mac/xcuitest/resource.txt | 1 + tools/gyp/test/mac/xcuitest/test.gyp | 69 + tools/gyp/test/make/dependencies.gyp | 15 + tools/gyp/test/make/gyptest-dependencies.py | 26 + tools/gyp/test/make/gyptest-noload.py | 57 + tools/gyp/test/make/main.cc | 12 + tools/gyp/test/make/main.h | 0 tools/gyp/test/make/noload/all.gyp | 18 + tools/gyp/test/make/noload/lib/shared.c | 3 + tools/gyp/test/make/noload/lib/shared.gyp | 16 + tools/gyp/test/make/noload/lib/shared.h | 1 + tools/gyp/test/make/noload/main.c | 9 + .../ar/gyptest-make_global_settings_ar.py | 106 + .../ar/make_global_settings_ar.gyp | 29 + .../basics/gyptest-make_global_settings.py | 51 + .../basics/make_global_settings.gyp | 17 + .../env-wrapper/gyptest-wrapper.py | 51 + .../env-wrapper/wrapper.gyp | 17 + .../full-toolchain/bar.cc | 1 + .../make_global_settings/full-toolchain/foo.c | 1 + .../gyptest-make_global_settings.py | 53 + .../full-toolchain/make_global_settings.gyp | 22 + .../full-toolchain/my_nm.py | 9 + .../full-toolchain/my_readelf.py | 9 + .../ld/gyptest-make_global_settings_ld.py | 101 + .../ld/make_global_settings_ld.gyp | 29 + .../wrapper/gyptest-wrapper.py | 52 + .../make_global_settings/wrapper/wrapper.gyp | 21 + tools/gyp/test/many-actions/file0 | 0 tools/gyp/test/many-actions/file1 | 0 tools/gyp/test/many-actions/file2 | 0 tools/gyp/test/many-actions/file3 | 0 tools/gyp/test/many-actions/file4 | 0 .../gyptest-many-actions-unsorted.py | 43 + .../test/many-actions/gyptest-many-actions.py | 29 + .../many-actions/many-actions-unsorted.gyp | 154 + tools/gyp/test/many-actions/many-actions.gyp | 1817 ++++++++ tools/gyp/test/module/gyptest-default.py | 28 + tools/gyp/test/module/src/lib1.c | 10 + tools/gyp/test/module/src/lib2.c | 10 + tools/gyp/test/module/src/module.gyp | 53 + tools/gyp/test/module/src/program.c | 111 + .../gyp/test/msvs/buildevents/buildevents.gyp | 14 + .../gyptest-msbuild-supports-prepostbuild.py | 24 + .../buildevents/gyptest-ninja-warnings.py | 29 + tools/gyp/test/msvs/buildevents/main.cc | 5 + .../msvs/config_attrs/gyptest-config_attrs.py | 41 + tools/gyp/test/msvs/config_attrs/hello.c | 11 + tools/gyp/test/msvs/config_attrs/hello.gyp | 21 + tools/gyp/test/msvs/express/base/base.gyp | 22 + tools/gyp/test/msvs/express/express.gyp | 19 + .../gyp/test/msvs/express/gyptest-express.py | 29 + .../test/msvs/external_builder/external.gyp | 68 + .../msvs/external_builder/external_builder.py | 9 + .../test/msvs/external_builder/gyptest-all.py | 59 + .../gyp/test/msvs/external_builder/hello.cpp | 10 + tools/gyp/test/msvs/external_builder/hello.z | 6 + .../msvs/external_builder/msbuild_action.py | 9 + .../msvs/external_builder/msbuild_rule.py | 11 + tools/gyp/test/msvs/filters/filters.gyp | 47 + .../test/msvs/filters/gyptest-filters-2008.py | 68 + .../test/msvs/filters/gyptest-filters-2010.py | 59 + .../test/msvs/list_excluded/gyptest-all.py | 51 + tools/gyp/test/msvs/list_excluded/hello.cpp | 10 + .../test/msvs/list_excluded/hello_exclude.gyp | 19 + .../gyp/test/msvs/list_excluded/hello_mac.cpp | 10 + .../msvs/missing_sources/gyptest-missing.py | 43 + .../msvs/missing_sources/hello_missing.gyp | 15 + .../action_fail.py | 7 + .../action_succeed.py | 7 + .../actions.gyp | 40 + .../gyptest.py | 24 + tools/gyp/test/msvs/props/AppName.props | 14 + tools/gyp/test/msvs/props/AppName.vsprops | 11 + tools/gyp/test/msvs/props/gyptest-props.py | 22 + tools/gyp/test/msvs/props/hello.c | 11 + tools/gyp/test/msvs/props/hello.gyp | 22 + .../test/msvs/rules_stdout_stderr/dummy.bar | 5 + .../test/msvs/rules_stdout_stderr/dummy.foo | 5 + .../gyptest-rules-stdout-stderr.py | 32 + .../msvs/rules_stdout_stderr/rule_stderr.py | 8 + .../msvs/rules_stdout_stderr/rule_stdout.py | 7 + .../rules-stdout-stderr.gyp | 52 + tools/gyp/test/msvs/shared_output/common.gypi | 17 + .../shared_output/gyptest-shared_output.py | 39 + tools/gyp/test/msvs/shared_output/hello.c | 12 + tools/gyp/test/msvs/shared_output/hello.gyp | 21 + .../gyp/test/msvs/shared_output/there/there.c | 12 + .../test/msvs/shared_output/there/there.gyp | 16 + tools/gyp/test/msvs/uldi2010/gyptest-all.py | 20 + tools/gyp/test/msvs/uldi2010/hello.c | 13 + tools/gyp/test/msvs/uldi2010/hello.gyp | 26 + tools/gyp/test/msvs/uldi2010/hello2.c | 10 + .../gyp/test/multiple-targets/gyptest-all.py | 30 + .../test/multiple-targets/gyptest-default.py | 30 + tools/gyp/test/multiple-targets/src/common.c | 7 + .../test/multiple-targets/src/multiple.gyp | 24 + tools/gyp/test/multiple-targets/src/prog1.c | 10 + tools/gyp/test/multiple-targets/src/prog2.c | 10 + .../gyptest-action-rule-hash.py | 32 + .../subdir/action-rule-hash.gyp | 29 + .../ninja/action-rule-hash/subdir/emit.py | 13 + .../gyptest-action-dependencies.py | 64 + .../test/ninja/action_dependencies/src/a.c | 10 + .../test/ninja/action_dependencies/src/a.h | 13 + .../src/action_dependencies.gyp | 88 + .../test/ninja/action_dependencies/src/b.c | 18 + .../test/ninja/action_dependencies/src/b.h | 13 + .../test/ninja/action_dependencies/src/c.c | 10 + .../test/ninja/action_dependencies/src/c.h | 13 + .../ninja/action_dependencies/src/emit.py | 11 + .../chained-dependency/chained-dependency.gyp | 53 + .../test/ninja/chained-dependency/chained.c | 5 + .../gyptest-chained-dependency.py | 30 + ...test-empty-and-non-empty-duplicate-name.py | 23 + .../subdir/included.gyp | 19 + .../test.gyp | 19 + .../gyptest-normalize-paths.py | 46 + .../test/ninja/normalize-paths-win/hello.cc | 7 + .../normalize-paths-win/normalize-paths.gyp | 68 + .../test/ninja/s-needs-no-depfiles/empty.s | 1 + .../gyptest-s-needs-no-depfiles.py | 41 + .../s-needs-no-depfiles.gyp | 13 + .../gyptest-solibs-avoid-relinking.py | 47 + .../test/ninja/solibs_avoid_relinking/main.cc | 5 + .../ninja/solibs_avoid_relinking/solib.cc | 8 + .../solibs_avoid_relinking.gyp | 38 + tools/gyp/test/ninja/use-console/foo.bar | 5 + .../ninja/use-console/gyptest-use-console.py | 29 + .../test/ninja/use-console/use-console.gyp | 60 + .../gyptest-use-custom-environment-files.py | 28 + .../use-custom-environment-files.cc | 7 + .../use-custom-environment-files.gyp | 15 + tools/gyp/test/no-cpp/gyptest-no-cpp.py | 53 + tools/gyp/test/no-cpp/src/call-f-main.c | 2 + tools/gyp/test/no-cpp/src/empty-main.c | 1 + tools/gyp/test/no-cpp/src/f.cc | 3 + tools/gyp/test/no-cpp/src/test.gyp | 25 + tools/gyp/test/no-output/gyptest-no-output.py | 21 + tools/gyp/test/no-output/src/nooutput.gyp | 17 + tools/gyp/test/product/gyptest-product.py | 43 + tools/gyp/test/product/hello.c | 15 + tools/gyp/test/product/product.gyp | 128 + .../prune_targets/gyptest-prune-targets.py | 66 + tools/gyp/test/prune_targets/lib1.cc | 6 + tools/gyp/test/prune_targets/lib2.cc | 6 + tools/gyp/test/prune_targets/lib3.cc | 6 + tools/gyp/test/prune_targets/lib_indirect.cc | 6 + tools/gyp/test/prune_targets/program.cc | 7 + tools/gyp/test/prune_targets/test1.gyp | 26 + tools/gyp/test/prune_targets/test2.gyp | 30 + tools/gyp/test/relative/foo/a/a.cc | 9 + tools/gyp/test/relative/foo/a/a.gyp | 13 + tools/gyp/test/relative/foo/a/c/c.cc | 9 + tools/gyp/test/relative/foo/a/c/c.gyp | 12 + tools/gyp/test/relative/foo/b/b.cc | 9 + tools/gyp/test/relative/foo/b/b.gyp | 9 + tools/gyp/test/relative/gyptest-default.py | 25 + tools/gyp/test/rename/filecase/file.c | 1 + .../rename/filecase/test-casesensitive.gyp | 15 + tools/gyp/test/rename/filecase/test.gyp | 14 + tools/gyp/test/rename/gyptest-filecase.py | 35 + tools/gyp/test/restat/gyptest-restat.py | 31 + .../test/restat/src/create_intermediate.py | 17 + tools/gyp/test/restat/src/restat.gyp | 50 + tools/gyp/test/restat/src/touch.py | 16 + .../gyp/test/rules/dirname/gyptest-dirname.py | 57 + tools/gyp/test/rules/dirname/src/actions.gyp | 15 + tools/gyp/test/rules/dirname/src/copy-file.py | 11 + .../test/rules/dirname/src/subdir/a/b/c.gencc | 8 + .../rules/dirname/src/subdir/a/b/c.printvars | 1 + .../dirname/src/subdir/foo/bar/baz.gencc | 8 + .../dirname/src/subdir/foo/bar/baz.printvars | 1 + .../dirname/src/subdir/input-rule-dirname.gyp | 140 + .../gyp/test/rules/dirname/src/subdir/main.cc | 14 + .../test/rules/dirname/src/subdir/nodir.gencc | 8 + .../rules/dirname/src/subdir/printvars.py | 14 + tools/gyp/test/rules/e2e/gyptest-all.py | 84 + tools/gyp/test/rules/e2e/gyptest-default.py | 70 + .../gyp/test/rules/e2e/gyptest-input-root.py | 26 + .../rules/e2e/gyptest-special-variables.py | 18 + tools/gyp/test/rules/e2e/src/actions.gyp | 23 + tools/gyp/test/rules/e2e/src/an_asm.S | 6 + tools/gyp/test/rules/e2e/src/as.bat | 7 + tools/gyp/test/rules/e2e/src/copy-file.py | 11 + .../test/rules/e2e/src/external/external.gyp | 66 + .../gyp/test/rules/e2e/src/external/file1.in | 1 + .../gyp/test/rules/e2e/src/external/file2.in | 1 + tools/gyp/test/rules/e2e/src/input-root.gyp | 24 + .../gyp/test/rules/e2e/src/noaction/file1.in | 1 + .../noaction/no_action_with_rules_fails.gyp | 37 + tools/gyp/test/rules/e2e/src/rule.py | 17 + tools/gyp/test/rules/e2e/src/somefile.ext | 0 .../test/rules/e2e/src/special-variables.gyp | 34 + .../test/rules/e2e/src/subdir1/executable.gyp | 37 + .../test/rules/e2e/src/subdir1/function1.in | 6 + .../test/rules/e2e/src/subdir1/function2.in | 6 + .../gyp/test/rules/e2e/src/subdir1/program.c | 12 + .../subdir2/both_rule_and_action_input.gyp | 50 + tools/gyp/test/rules/e2e/src/subdir2/file1.in | 1 + tools/gyp/test/rules/e2e/src/subdir2/file2.in | 1 + .../test/rules/e2e/src/subdir2/never_used.gyp | 31 + .../test/rules/e2e/src/subdir2/no_action.gyp | 38 + .../test/rules/e2e/src/subdir2/no_inputs.gyp | 32 + tools/gyp/test/rules/e2e/src/subdir2/none.gyp | 33 + .../gyp/test/rules/e2e/src/subdir2/program.c | 12 + .../rules/e2e/src/subdir3/executable2.gyp | 37 + .../test/rules/e2e/src/subdir3/function3.in | 6 + .../gyp/test/rules/e2e/src/subdir3/program.c | 10 + .../rules/e2e/src/subdir4/asm-function.assem | 10 + .../test/rules/e2e/src/subdir4/build-asm.gyp | 49 + .../gyp/test/rules/e2e/src/subdir4/program.c | 19 + tools/gyp/test/rules/rebuild/gyptest-all.py | 70 + .../gyp/test/rules/rebuild/gyptest-default.py | 91 + tools/gyp/test/rules/rebuild/src/main.c | 12 + .../test/rules/rebuild/src/make-sources.py | 19 + tools/gyp/test/rules/rebuild/src/prog1.in | 7 + tools/gyp/test/rules/rebuild/src/prog2.in | 7 + .../test/rules/rebuild/src/same_target.gyp | 31 + .../gyptest-use-built-dependencies.py | 23 + .../rules/use-built-dependencies/src/main.cc | 17 + .../src/use-built-dependencies-rule.gyp | 42 + .../variables/gyptest-rules-variables.py | 35 + .../gyp/test/rules/variables/src/input_ext.c | 9 + .../rules/variables/src/input_name/test.c | 9 + .../variables/src/input_path/subdir/test.c | 9 + .../variables/src/subdir/input_dirname.c | 9 + .../test/rules/variables/src/subdir/test.c | 18 + .../rules/variables/src/test.input_root.c | 9 + .../test/rules/variables/src/variables.gyp | 40 + tools/gyp/test/same-gyp-name/gyptest-all.py | 38 + .../gyp/test/same-gyp-name/gyptest-default.py | 38 + .../gyp/test/same-gyp-name/gyptest-library.py | 20 + .../test/same-gyp-name/library/one/sub.gyp | 11 + tools/gyp/test/same-gyp-name/library/test.gyp | 15 + .../test/same-gyp-name/library/two/sub.gyp | 11 + tools/gyp/test/same-gyp-name/src/all.gyp | 16 + .../same-gyp-name/src/subdir1/executable.gyp | 15 + .../test/same-gyp-name/src/subdir1/main1.cc | 6 + .../same-gyp-name/src/subdir2/executable.gyp | 15 + .../test/same-gyp-name/src/subdir2/main2.cc | 6 + .../same-rule-output-file-name/gyptest-all.py | 23 + .../src/subdir1/subdir1.gyp | 30 + .../src/subdir2/subdir2.gyp | 30 + .../src/subdirs.gyp | 16 + .../same-rule-output-file-name/src/touch.py | 11 + .../test/same-source-file-name/gyptest-all.py | 34 + .../same-source-file-name/gyptest-default.py | 34 + .../gyptest-pass-executable.py | 33 + .../gyptest-pass-shared.py | 18 + .../same-source-file-name/gyptest-static.py | 20 + .../test/same-source-file-name/src/all.gyp | 30 + .../src/double-executable.gyp | 21 + .../src/double-shared.gyp | 27 + .../src/double-static.gyp | 22 + .../gyp/test/same-source-file-name/src/func.c | 6 + .../test/same-source-file-name/src/prog1.c | 16 + .../test/same-source-file-name/src/prog2.c | 16 + .../test/same-source-file-name/src/prog3.c | 18 + .../same-source-file-name/src/subdir1/func.c | 6 + .../same-source-file-name/src/subdir2/func.c | 6 + .../gyptest-all.py | 29 + .../src/subdir1/subdir1.gyp | 66 + .../src/subdir2/subdir2.gyp | 66 + .../src/subdirs.gyp | 16 + .../src/touch.py | 11 + .../gyptest-same-target-name.py | 18 + tools/gyp/test/same-target-name/src/all.gyp | 16 + .../test/same-target-name/src/executable1.gyp | 15 + .../test/same-target-name/src/executable2.gyp | 15 + tools/gyp/test/sanitize-rule-names/blah.S | 0 .../gyptest-sanitize-rule-names.py | 17 + tools/gyp/test/sanitize-rule-names/hello.cc | 7 + .../sanitize-rule-names.gyp | 27 + tools/gyp/test/sanitize-rule-names/script.py | 10 + tools/gyp/test/self-dependency/common.gypi | 13 + tools/gyp/test/self-dependency/dep.gyp | 23 + .../gyptest-self-dependency.py | 19 + .../test/self-dependency/self_dependency.gyp | 15 + tools/gyp/test/sibling/gyptest-all.py | 42 + tools/gyp/test/sibling/gyptest-relocate.py | 44 + tools/gyp/test/sibling/src/build/all.gyp | 16 + tools/gyp/test/sibling/src/prog1/prog1.c | 7 + tools/gyp/test/sibling/src/prog1/prog1.gyp | 15 + tools/gyp/test/sibling/src/prog2/prog2.c | 7 + tools/gyp/test/sibling/src/prog2/prog2.gyp | 15 + tools/gyp/test/small/gyptest-small.py | 53 + .../gyptest-standalone-static-library.py | 50 + .../standalone-static-library/invalid.gyp | 16 + .../test/standalone-static-library/mylib.c | 7 + .../test/standalone-static-library/mylib.gyp | 26 + .../gyp/test/standalone-static-library/prog.c | 7 + .../gyp/test/standalone/gyptest-standalone.py | 36 + tools/gyp/test/standalone/standalone.gyp | 12 + .../test/subdirectory/gyptest-SYMROOT-all.py | 36 + .../subdirectory/gyptest-SYMROOT-default.py | 37 + .../test/subdirectory/gyptest-subdir-all.py | 26 + .../subdirectory/gyptest-subdir-default.py | 34 + .../test/subdirectory/gyptest-subdir2-deep.py | 25 + .../gyp/test/subdirectory/gyptest-top-all.py | 43 + .../test/subdirectory/gyptest-top-default.py | 43 + tools/gyp/test/subdirectory/src/prog1.c | 7 + tools/gyp/test/subdirectory/src/prog1.gyp | 21 + .../gyp/test/subdirectory/src/subdir/prog2.c | 7 + .../test/subdirectory/src/subdir/prog2.gyp | 18 + .../subdirectory/src/subdir/subdir2/prog3.c | 7 + .../subdirectory/src/subdir/subdir2/prog3.gyp | 18 + tools/gyp/test/subdirectory/src/symroot.gypi | 16 + tools/gyp/test/symlinks/gyptest-symlinks.py | 66 + tools/gyp/test/symlinks/hello.c | 12 + tools/gyp/test/symlinks/hello.gyp | 15 + tools/gyp/test/target/gyptest-target.py | 37 + tools/gyp/test/target/hello.c | 7 + tools/gyp/test/target/target.gyp | 24 + tools/gyp/test/toolsets/gyptest-toolsets.py | 31 + tools/gyp/test/toolsets/main.cc | 13 + tools/gyp/test/toolsets/toolsets.cc | 11 + tools/gyp/test/toolsets/toolsets.gyp | 62 + tools/gyp/test/toolsets/toolsets_shared.cc | 11 + .../test/toplevel-dir/gyptest-toplevel-dir.py | 31 + tools/gyp/test/toplevel-dir/src/sub1/main.gyp | 18 + tools/gyp/test/toplevel-dir/src/sub1/prog1.c | 7 + tools/gyp/test/toplevel-dir/src/sub2/prog2.c | 7 + .../gyp/test/toplevel-dir/src/sub2/prog2.gyp | 15 + .../variables/commands/commands-repeated.gyp | 129 + .../commands/commands-repeated.gyp.stdout | 136 + .../commands/commands-repeated.gypd.golden | 77 + .../gyp/test/variables/commands/commands.gyp | 92 + .../commands/commands.gyp.ignore-env.stdout | 96 + .../variables/commands/commands.gyp.stdout | 96 + .../variables/commands/commands.gypd.golden | 66 + .../gyp/test/variables/commands/commands.gypi | 23 + .../commands/gyptest-commands-ignore-env.py | 45 + .../gyptest-commands-repeated-multidir.py | 23 + .../commands/gyptest-commands-repeated.py | 41 + .../variables/commands/gyptest-commands.py | 38 + .../repeated_multidir/dir_1/test_1.gyp | 13 + .../repeated_multidir/dir_2/test_2.gyp | 13 + .../commands/repeated_multidir/main.gyp | 16 + .../repeated_multidir/print_cwd_basename.py | 10 + .../repeated_command_common.gypi | 25 + tools/gyp/test/variables/commands/test.py | 7 + .../gyp/test/variables/commands/update_golden | 11 + tools/gyp/test/variables/empty/empty.gyp | 13 + tools/gyp/test/variables/empty/empty.gypi | 9 + .../gyp/test/variables/empty/gyptest-empty.py | 19 + .../variables/filelist/filelist.gyp.stdout | 26 + .../variables/filelist/filelist.gypd.golden | 43 + .../filelist/gyptest-filelist-golden.py | 53 + .../variables/filelist/gyptest-filelist.py | 29 + .../gyp/test/variables/filelist/src/dummy.py | 5 + .../test/variables/filelist/src/filelist.gyp | 93 + .../test/variables/filelist/src/filelist2.gyp | 40 + .../gyp/test/variables/filelist/update_golden | 8 + .../variables/latelate/gyptest-latelate.py | 25 + .../test/variables/latelate/src/latelate.gyp | 34 + .../test/variables/latelate/src/program.cc | 13 + .../variables/variable-in-path/C1/hello.cc | 7 + .../gyptest-variable-in-path.py | 23 + .../variable-in-path/variable-in-path.gyp | 31 + tools/gyp/test/win/asm-files/asm-files.gyp | 17 + tools/gyp/test/win/asm-files/b.s | 0 tools/gyp/test/win/asm-files/c.S | 0 tools/gyp/test/win/asm-files/hello.cc | 7 + .../batch-file-action/batch-file-action.gyp | 21 + tools/gyp/test/win/batch-file-action/infile | 1 + .../test/win/batch-file-action/somecmd.bat | 5 + tools/gyp/test/win/command-quote/a.S | 0 .../win/command-quote/bat with spaces.bat | 7 + .../test/win/command-quote/command-quote.gyp | 79 + tools/gyp/test/win/command-quote/go.bat | 7 + .../subdir/and/another/in-subdir.gyp | 27 + .../compiler-flags/additional-include-dirs.cc | 10 + .../additional-include-dirs.gyp | 20 + .../win/compiler-flags/additional-options.cc | 10 + .../win/compiler-flags/additional-options.gyp | 31 + .../gyp/test/win/compiler-flags/analysis.gyp | 40 + .../compiler-flags/buffer-security-check.gyp | 51 + .../win/compiler-flags/buffer-security.cc | 12 + .../calling-convention-cdecl.def | 6 + .../calling-convention-fastcall.def | 6 + .../calling-convention-stdcall.def | 6 + .../calling-convention-vectorcall.def | 6 + .../win/compiler-flags/calling-convention.cc | 6 + .../win/compiler-flags/calling-convention.gyp | 66 + .../win/compiler-flags/character-set-mbcs.cc | 11 + .../compiler-flags/character-set-unicode.cc | 15 + .../test/win/compiler-flags/character-set.gyp | 35 + .../win/compiler-flags/compile-as-managed.cc | 9 + .../win/compiler-flags/compile-as-managed.gyp | 29 + .../win/compiler-flags/compile-as-winrt.cc | 12 + .../win/compiler-flags/compile-as-winrt.gyp | 20 + .../test/win/compiler-flags/debug-format.gyp | 48 + .../default-char-is-unsigned.cc | 15 + .../default-char-is-unsigned.gyp | 20 + .../disable-specific-warnings.cc | 9 + .../disable-specific-warnings.gyp | 29 + .../enable-enhanced-instruction-set.cc | 28 + .../enable-enhanced-instruction-set.gyp | 68 + .../compiler-flags/exception-handling-on.cc | 24 + .../win/compiler-flags/exception-handling.gyp | 46 + .../floating-point-model-fast.cc | 19 + .../floating-point-model-precise.cc | 19 + .../floating-point-model-strict.cc | 19 + .../compiler-flags/floating-point-model.gyp | 43 + .../force-include-files-with-precompiled.cc | 10 + .../win/compiler-flags/force-include-files.cc | 8 + .../compiler-flags/force-include-files.gyp | 36 + .../compiler-flags/function-level-linking.cc | 11 + .../compiler-flags/function-level-linking.gyp | 28 + tools/gyp/test/win/compiler-flags/hello.cc | 7 + .../test/win/compiler-flags/optimizations.gyp | 207 + .../win/compiler-flags/pdbname-override.gyp | 26 + tools/gyp/test/win/compiler-flags/pdbname.cc | 7 + tools/gyp/test/win/compiler-flags/pdbname.gyp | 24 + tools/gyp/test/win/compiler-flags/precomp.cc | 6 + tools/gyp/test/win/compiler-flags/rtti-on.cc | 11 + tools/gyp/test/win/compiler-flags/rtti.gyp | 37 + .../test/win/compiler-flags/runtime-checks.cc | 11 + .../win/compiler-flags/runtime-checks.gyp | 29 + .../win/compiler-flags/runtime-library-md.cc | 19 + .../win/compiler-flags/runtime-library-mdd.cc | 19 + .../win/compiler-flags/runtime-library-mt.cc | 19 + .../win/compiler-flags/runtime-library-mtd.cc | 19 + .../win/compiler-flags/runtime-library.gyp | 48 + .../test/win/compiler-flags/subdir/header.h | 0 .../treat-wchar-t-as-built-in-type.gyp | 33 + .../treat-wchar-t-as-built-in-type1.cc | 11 + .../treat-wchar-t-as-built-in-type2.cc | 11 + tools/gyp/test/win/compiler-flags/uninit.cc | 13 + .../win/compiler-flags/warning-as-error.cc | 9 + .../win/compiler-flags/warning-as-error.gyp | 37 + .../test/win/compiler-flags/warning-level.gyp | 115 + .../test/win/compiler-flags/warning-level1.cc | 8 + .../test/win/compiler-flags/warning-level2.cc | 14 + .../test/win/compiler-flags/warning-level3.cc | 11 + .../test/win/compiler-flags/warning-level4.cc | 10 + tools/gyp/test/win/enable-winrt/dllmain.cc | 30 + .../test/win/enable-winrt/enable-winrt.gyp | 39 + ...yptest-generator-output-different-drive.py | 44 + .../generator-output-different-drive/prog.c | 10 + .../prog.gyp} | 15 +- tools/gyp/test/win/gyptest-asm-files.py | 26 + .../win/gyptest-cl-additional-include-dirs.py | 22 + .../test/win/gyptest-cl-additional-options.py | 28 + tools/gyp/test/win/gyptest-cl-analysis.py | 30 + .../win/gyptest-cl-buffer-security-check.py | 53 + .../test/win/gyptest-cl-calling-convention.py | 22 + .../gyp/test/win/gyptest-cl-character-set.py | 22 + .../test/win/gyptest-cl-compile-as-managed.py | 24 + .../test/win/gyptest-cl-compile-as-winrt.py | 20 + tools/gyp/test/win/gyptest-cl-debug-format.py | 39 + .../gyptest-cl-default-char-is-unsigned.py | 22 + .../gyptest-cl-disable-specific-warnings.py | 32 + ...test-cl-enable-enhanced-instruction-set.py | 49 + .../test/win/gyptest-cl-exception-handling.py | 33 + .../win/gyptest-cl-floating-point-model.py | 22 + .../win/gyptest-cl-force-include-files.py | 22 + .../win/gyptest-cl-function-level-linking.py | 52 + .../gyp/test/win/gyptest-cl-optimizations.py | 92 + .../test/win/gyptest-cl-pdbname-override.py | 27 + tools/gyp/test/win/gyptest-cl-pdbname.py | 30 + tools/gyp/test/win/gyptest-cl-rtti.py | 30 + .../gyp/test/win/gyptest-cl-runtime-checks.py | 30 + .../test/win/gyptest-cl-runtime-library.py | 22 + ...ptest-cl-treat-wchar-t-as-built-in-type.py | 22 + .../test/win/gyptest-cl-warning-as-error.py | 30 + .../gyp/test/win/gyptest-cl-warning-level.py | 41 + tools/gyp/test/win/gyptest-command-quote.py | 42 + tools/gyp/test/win/gyptest-crosscompile-ar.py | 29 + tools/gyp/test/win/gyptest-lib-ltcg.py | 22 + .../test/win/gyptest-link-additional-deps.py | 22 + .../win/gyptest-link-additional-options.py | 22 + tools/gyp/test/win/gyptest-link-aslr.py | 35 + .../gyp/test/win/gyptest-link-base-address.py | 62 + tools/gyp/test/win/gyptest-link-debug-info.py | 26 + .../gyp/test/win/gyptest-link-default-libs.py | 22 + tools/gyp/test/win/gyptest-link-deffile.py | 43 + tools/gyp/test/win/gyptest-link-defrelink.py | 56 + .../test/win/gyptest-link-delay-load-dlls.py | 35 + .../test/win/gyptest-link-embed-manifest.py | 86 + tools/gyp/test/win/gyptest-link-enable-uac.py | 101 + .../gyptest-link-enable-winrt-app-revision.py | 38 + ...nk-enable-winrt-target-platform-version.py | 43 + .../gyp/test/win/gyptest-link-enable-winrt.py | 35 + .../test/win/gyptest-link-entrypointsymbol.py | 24 + tools/gyp/test/win/gyptest-link-fixed-base.py | 40 + .../gyptest-link-force-symbol-reference.py | 26 + .../win/gyptest-link-generate-manifest.py | 94 + .../gyp/test/win/gyptest-link-incremental.py | 37 + .../win/gyptest-link-large-address-aware.py | 35 + tools/gyp/test/win/gyptest-link-large-pdb.py | 76 + .../test/win/gyptest-link-library-adjust.py | 21 + .../win/gyptest-link-library-directories.py | 35 + tools/gyp/test/win/gyptest-link-ltcg.py | 47 + tools/gyp/test/win/gyptest-link-mapfile.py | 44 + .../gyp/test/win/gyptest-link-nodefaultlib.py | 24 + .../gyp/test/win/gyptest-link-noimportlib.py | 30 + tools/gyp/test/win/gyptest-link-nxcompat.py | 37 + tools/gyp/test/win/gyptest-link-opt-icf.py | 41 + tools/gyp/test/win/gyptest-link-opt-ref.py | 40 + tools/gyp/test/win/gyptest-link-ordering.py | 103 + tools/gyp/test/win/gyptest-link-outputfile.py | 28 + .../test/win/gyptest-link-pdb-no-output.py | 25 + tools/gyp/test/win/gyptest-link-pdb-output.py | 33 + tools/gyp/test/win/gyptest-link-pdb.py | 35 + tools/gyp/test/win/gyptest-link-pgo.py | 75 + tools/gyp/test/win/gyptest-link-profile.py | 37 + .../test/win/gyptest-link-restat-importlib.py | 47 + tools/gyp/test/win/gyptest-link-safeseh.py | 46 + tools/gyp/test/win/gyptest-link-shard.py | 30 + tools/gyp/test/win/gyptest-link-stacksize.py | 62 + tools/gyp/test/win/gyptest-link-subsystem.py | 38 + .../test/win/gyptest-link-target-machine.py | 28 + tools/gyp/test/win/gyptest-link-tsaware.py | 33 + .../gyptest-link-uldi-depending-on-module.py | 24 + tools/gyp/test/win/gyptest-link-uldi.py | 28 + .../win/gyptest-link-unsupported-manifest.py | 27 + .../test/win/gyptest-link-update-manifest.py | 104 + .../win/gyptest-link-warnings-as-errors.py | 24 + .../gyp/test/win/gyptest-long-command-line.py | 23 + .../gyp/test/win/gyptest-macro-projectname.py | 24 + tools/gyp/test/win/gyptest-macro-targetext.py | 26 + .../test/win/gyptest-macro-targetfilename.py | 37 + .../gyp/test/win/gyptest-macro-targetname.py | 29 + .../gyp/test/win/gyptest-macro-targetpath.py | 30 + .../test/win/gyptest-macro-vcinstalldir.py | 24 + .../test/win/gyptest-macros-containing-gyp.py | 21 + .../gyptest-macros-in-inputs-and-outputs.py | 25 + tools/gyp/test/win/gyptest-midl-excluded.py | 22 + .../gyp/test/win/gyptest-midl-includedirs.py | 21 + tools/gyp/test/win/gyptest-midl-rules.py | 28 + tools/gyp/test/win/gyptest-ml-safeseh.py | 22 + .../gyp/test/win/gyptest-quoting-commands.py | 25 + tools/gyp/test/win/gyptest-rc-build.py | 29 + tools/gyp/test/win/gyptest-sys.py | 30 + tools/gyp/test/win/gyptest-system-include.py | 21 + tools/gyp/test/win/idl-excluded/bad.idl | 6 + tools/gyp/test/win/idl-excluded/copy-file.py | 11 + .../test/win/idl-excluded/idl-excluded.gyp | 58 + tools/gyp/test/win/idl-excluded/program.cc | 7 + tools/gyp/test/win/idl-includedirs/hello.cc | 7 + .../win/idl-includedirs/idl-includedirs.gyp | 26 + .../test/win/idl-includedirs/subdir/bar.idl | 13 + .../test/win/idl-includedirs/subdir/foo.idl | 14 + tools/gyp/test/win/idl-rules/Window.idl | 9 + tools/gyp/test/win/idl-rules/basic-idl.gyp | 71 + .../test/win/idl-rules/history_indexer.idl | 17 + .../win/idl-rules/history_indexer_user.cc | 15 + tools/gyp/test/win/idl-rules/idl_compiler.py | 17 + .../gyp/test/win/importlib/dll_no_exports.cc | 9 + tools/gyp/test/win/importlib/has-exports.cc | 10 + tools/gyp/test/win/importlib/hello.cc | 9 + tools/gyp/test/win/importlib/importlib.gyp | 30 + tools/gyp/test/win/importlib/noimplib.gyp | 16 + tools/gyp/test/win/large-pdb/dllmain.cc | 9 + tools/gyp/test/win/large-pdb/large-pdb.gyp | 98 + tools/gyp/test/win/large-pdb/main.cc | 7 + tools/gyp/test/win/lib-crosscompile/answer.cc | 9 + tools/gyp/test/win/lib-crosscompile/answer.h | 5 + .../test/win/lib-crosscompile/use_host_ar.gyp | 17 + tools/gyp/test/win/lib-flags/answer.cc | 9 + tools/gyp/test/win/lib-flags/answer.h | 5 + tools/gyp/test/win/lib-flags/ltcg.gyp | 21 + tools/gyp/test/win/linker-flags/a/x.cc | 7 + tools/gyp/test/win/linker-flags/a/z.cc | 7 + .../test/win/linker-flags/additional-deps.cc | 10 + .../test/win/linker-flags/additional-deps.gyp | 30 + .../win/linker-flags/additional-options.gyp | 29 + tools/gyp/test/win/linker-flags/aslr.gyp | 35 + tools/gyp/test/win/linker-flags/b/y.cc | 7 + .../test/win/linker-flags/base-address.gyp | 38 + .../gyp/test/win/linker-flags/debug-info.gyp | 28 + .../win/linker-flags/deffile-multiple.gyp | 17 + tools/gyp/test/win/linker-flags/deffile.cc | 13 + tools/gyp/test/win/linker-flags/deffile.def | 8 + tools/gyp/test/win/linker-flags/deffile.gyp | 38 + .../test/win/linker-flags/delay-load-dlls.gyp | 35 + tools/gyp/test/win/linker-flags/delay-load.cc | 10 + .../test/win/linker-flags/embed-manifest.gyp | 109 + .../gyp/test/win/linker-flags/enable-uac.gyp | 45 + .../test/win/linker-flags/entrypointsymbol.cc | 13 + .../win/linker-flags/entrypointsymbol.gyp | 28 + .../gyp/test/win/linker-flags/extra.manifest | 11 + .../gyp/test/win/linker-flags/extra2.manifest | 11 + .../gyp/test/win/linker-flags/fixed-base.gyp | 52 + .../linker-flags/force-symbol-reference.gyp | 39 + .../win/linker-flags/generate-manifest.gyp | 166 + tools/gyp/test/win/linker-flags/hello.cc | 7 + .../gyp/test/win/linker-flags/incremental.gyp | 65 + .../gyp/test/win/linker-flags/inline_test.cc | 12 + tools/gyp/test/win/linker-flags/inline_test.h | 5 + .../test/win/linker-flags/inline_test_main.cc | 15 + .../win/linker-flags/large-address-aware.gyp | 28 + .../test/win/linker-flags/library-adjust.cc | 10 + .../test/win/linker-flags/library-adjust.gyp | 16 + .../library-directories-define.cc | 7 + .../library-directories-reference.cc | 10 + .../win/linker-flags/library-directories.gyp | 42 + .../test/win/linker-flags/link-ordering.gyp | 95 + .../gyp/test/win/linker-flags/link-warning.cc | 10 + tools/gyp/test/win/linker-flags/ltcg.gyp | 42 + tools/gyp/test/win/linker-flags/main-crt.c | 8 + .../win/linker-flags/manifest-in-comment.cc | 13 + tools/gyp/test/win/linker-flags/mapfile.cc | 12 + tools/gyp/test/win/linker-flags/mapfile.gyp | 45 + .../test/win/linker-flags/no-default-libs.cc | 18 + .../test/win/linker-flags/no-default-libs.gyp | 13 + .../gyp/test/win/linker-flags/nodefaultlib.cc | 13 + .../test/win/linker-flags/nodefaultlib.gyp | 30 + tools/gyp/test/win/linker-flags/nxcompat.gyp | 35 + tools/gyp/test/win/linker-flags/opt-icf.cc | 29 + tools/gyp/test/win/linker-flags/opt-icf.gyp | 63 + tools/gyp/test/win/linker-flags/opt-ref.cc | 11 + tools/gyp/test/win/linker-flags/opt-ref.gyp | 56 + .../gyp/test/win/linker-flags/outputfile.gyp | 58 + .../gyp/test/win/linker-flags/pdb-output.gyp | 49 + tools/gyp/test/win/linker-flags/pgo.gyp | 143 + tools/gyp/test/win/linker-flags/profile.gyp | 50 + .../win/linker-flags/program-database.gyp | 40 + tools/gyp/test/win/linker-flags/safeseh.gyp | 79 + .../test/win/linker-flags/safeseh_hello.cc | 11 + .../test/win/linker-flags/safeseh_zero.asm | 10 + .../test/win/linker-flags/safeseh_zero64.asm | 9 + tools/gyp/test/win/linker-flags/stacksize.gyp | 44 + .../test/win/linker-flags/subdir/library.gyp | 13 + .../win/linker-flags/subsystem-windows.cc | 9 + tools/gyp/test/win/linker-flags/subsystem.gyp | 70 + .../test/win/linker-flags/target-machine.gyp | 48 + tools/gyp/test/win/linker-flags/tsaware.gyp | 28 + .../win/linker-flags/unsupported-manifest.gyp | 13 + tools/gyp/test/win/linker-flags/update_pgd.py | 35 + .../test/win/linker-flags/warn-as-error.gyp | 33 + tools/gyp/test/win/linker-flags/x.cc | 7 + tools/gyp/test/win/linker-flags/y.cc | 7 + tools/gyp/test/win/linker-flags/z.cc | 7 + .../test/win/long-command-line/function.cc | 7 + tools/gyp/test/win/long-command-line/hello.cc | 7 + .../long-command-line/long-command-line.gyp | 54 + tools/gyp/test/win/ml-safeseh/a.asm | 10 + tools/gyp/test/win/ml-safeseh/hello.cc | 11 + tools/gyp/test/win/ml-safeseh/ml-safeseh.gyp | 24 + tools/gyp/test/win/precompiled/gyptest-all.py | 21 + tools/gyp/test/win/precompiled/hello.c | 14 + tools/gyp/test/win/precompiled/hello.gyp | 28 + tools/gyp/test/win/precompiled/hello2.c | 13 + tools/gyp/test/win/precompiled/precomp.c | 8 + tools/gyp/test/win/rc-build/Resource.h | 26 + tools/gyp/test/win/rc-build/hello.cpp | 30 + tools/gyp/test/win/rc-build/hello.gyp | 92 + tools/gyp/test/win/rc-build/hello.h | 3 + tools/gyp/test/win/rc-build/hello.ico | Bin 0 -> 23558 bytes tools/gyp/test/win/rc-build/hello.rc | 86 + tools/gyp/test/win/rc-build/hello3.rc | 87 + tools/gyp/test/win/rc-build/small.ico | Bin 0 -> 23558 bytes tools/gyp/test/win/rc-build/subdir/hello2.rc | 87 + tools/gyp/test/win/rc-build/subdir/include.h | 1 + tools/gyp/test/win/rc-build/targetver.h | 24 + tools/gyp/test/win/shard/hello.cc | 7 + tools/gyp/test/win/shard/hello1.cc | 7 + tools/gyp/test/win/shard/hello2.cc | 7 + tools/gyp/test/win/shard/hello3.cc | 7 + tools/gyp/test/win/shard/hello4.cc | 7 + tools/gyp/test/win/shard/shard.gyp | 31 + tools/gyp/test/win/shard/shard_ref.gyp | 41 + .../gyp/test/win/system-include/bar/header.h | 0 .../win/system-include/common/commonheader.h | 0 .../gyp/test/win/system-include/foo/header.h | 0 tools/gyp/test/win/system-include/main.cc | 4 + tools/gyp/test/win/system-include/test.gyp | 26 + tools/gyp/test/win/uldi/a.cc | 7 + tools/gyp/test/win/uldi/b.cc | 7 + tools/gyp/test/win/uldi/dll.cc | 6 + tools/gyp/test/win/uldi/exe.cc | 7 + tools/gyp/test/win/uldi/main.cc | 10 + .../win/uldi/uldi-depending-on-module.gyp | 42 + tools/gyp/test/win/uldi/uldi.gyp | 45 + tools/gyp/test/win/vs-macros/as.py | 20 + .../gyp/test/win/vs-macros/containing-gyp.gyp | 39 + tools/gyp/test/win/vs-macros/do_stuff.py | 8 + tools/gyp/test/win/vs-macros/hello.cc | 7 + .../win/vs-macros/input-output-macros.gyp | 32 + tools/gyp/test/win/vs-macros/input.S | 0 tools/gyp/test/win/vs-macros/projectname.gyp | 29 + tools/gyp/test/win/vs-macros/stuff.blah | 1 + tools/gyp/test/win/vs-macros/targetext.gyp | 59 + .../gyp/test/win/vs-macros/targetfilename.gyp | 59 + tools/gyp/test/win/vs-macros/targetname.gyp | 52 + tools/gyp/test/win/vs-macros/targetpath.gyp | 59 + tools/gyp/test/win/vs-macros/test_exists.py | 10 + tools/gyp/test/win/vs-macros/vcinstalldir.gyp | 41 + .../win-driver-target-type.c | 10 + .../win-driver-target-type.gyp | 32 + .../win-driver-target-type.h | 13 + .../win-driver-target-type.rc | 14 + .../win/win-tool/copies_readonly_files.gyp | 29 + ...gyptest-win-tool-handles-readonly-files.py | 55 + .../win/winrt-app-type-revision/dllmain.cc | 30 + .../winrt-app-type-revision.gyp | 35 + .../winrt-target-platform-version/dllmain.cc | 30 + .../winrt-target-platform-version.gyp | 45 + .../xcode-ninja/list_excluded/gyptest-all.py | 49 + .../test/xcode-ninja/list_excluded/hello.cpp | 7 + .../list_excluded/hello_exclude.gyp | 19 + .../list_excluded/hello_excluded.cpp | 7 + tools/gyp/testlib/README.txt | 16 + tools/gyp/testlib/SConsLib/TestCmd.py | 1929 ++++++++ tools/gyp/testlib/SConsLib/TestCommon.py | 760 +++ .../gyp/testlib/SConsLib/TestUnit/__init__.py | 5 + tools/gyp/testlib/SConsLib/TestUnit/cli.py | 32 + .../testlib/SConsLib/TestUnit/taprunner.py | 130 + tools/gyp/testlib/SConsLib/__init__.py | 0 tools/gyp/testlib/TestGyp.py | 1455 ++++++ tools/gyp/tools/graphviz.py | 34 +- tools/gyp/tools/pretty_gyp.py | 12 +- tools/gyp/tools/pretty_sln.py | 50 +- tools/gyp/tools/pretty_vcproj.py | 79 +- .../gyp/tools/vssetup.powershell/LICENSE.txt | 8 + ...icrosoft.VisualStudio.Setup.PowerShell.dll | Bin 0 -> 39424 bytes .../gyp/tools/vssetup.powershell/VSQuery.ps1 | 4 + .../gyp/tools/vssetup.powershell/VSSetup.psd1 | 15 + .../vssetup.powershell/VSSetup.types.ps1xml | 66 + .../vssetup.powershell/about_VSSetup.help.txt | 46 + 1658 files changed, 57276 insertions(+), 8848 deletions(-) create mode 100644 tools/gyp/.travis.yml delete mode 100644 tools/gyp/AUTHORS delete mode 100644 tools/gyp/DEPS delete mode 100644 tools/gyp/OWNERS delete mode 100644 tools/gyp/PRESUBMIT.py create mode 100644 tools/gyp/Pipfile create mode 100644 tools/gyp/Pipfile.lock create mode 100644 tools/gyp/azure-pipelines.yml delete mode 100755 tools/gyp/buildbot/buildbot_run.py delete mode 100644 tools/gyp/buildbot/commit_queue/OWNERS delete mode 100644 tools/gyp/buildbot/commit_queue/README delete mode 100644 tools/gyp/buildbot/commit_queue/cq_config.json delete mode 100644 tools/gyp/codereview.settings delete mode 100755 tools/gyp/gyp.bat rename tools/gyp/{pylib/gyp => gyp/MSVS}/MSVSNew.py (53%) rename tools/gyp/{pylib/gyp => gyp/MSVS}/MSVSSettings.py (97%) rename tools/gyp/{pylib/gyp => gyp/MSVS}/MSVSToolFile.py (82%) create mode 100644 tools/gyp/gyp/MSVS/MSVSVersion.py create mode 100644 tools/gyp/gyp/MSVS/__init__.py create mode 100644 tools/gyp/gyp/Makefile.tmpl rename tools/gyp/{pylib/gyp/generator/make.py => gyp/MakefileWriter.py} (51%) create mode 100644 tools/gyp/gyp/NinjaWriter.py create mode 100644 tools/gyp/gyp/XCodeDetect.py rename tools/gyp/{pylib => }/gyp/__init__.py (66%) mode change 100755 => 100644 rename tools/gyp/{pylib/gyp => gyp/buildtime_helpers}/flock_tool.py (79%) mode change 100755 => 100644 rename tools/gyp/{data/win => gyp/buildtime_helpers}/large-pdb-shim.cc (100%) rename tools/gyp/{pylib/gyp => gyp/buildtime_helpers}/mac_tool.py (97%) mode change 100755 => 100644 rename tools/gyp/{pylib/gyp => gyp/buildtime_helpers}/win_tool.py (83%) mode change 100755 => 100644 rename tools/gyp/{pylib => }/gyp/common.py (87%) rename tools/gyp/{pylib => }/gyp/easy_xml.py (89%) rename tools/gyp/{pylib => }/gyp/generator/__init__.py (100%) rename tools/gyp/{pylib => }/gyp/generator/analyzer.py (92%) rename tools/gyp/{pylib => }/gyp/generator/cmake.py (86%) rename tools/gyp/{pylib => }/gyp/generator/dump_dependency_json.py (84%) rename tools/gyp/{pylib => }/gyp/generator/eclipse.py (86%) rename tools/gyp/{pylib => }/gyp/generator/gypd.py (93%) rename tools/gyp/{pylib => }/gyp/generator/gypsh.py (84%) create mode 100644 tools/gyp/gyp/generator/make.py rename tools/gyp/{pylib => }/gyp/generator/msvs.py (77%) create mode 100644 tools/gyp/gyp/generator/ninja.py rename tools/gyp/{pylib => }/gyp/generator/xcode.py (93%) rename tools/gyp/{pylib/gyp => gyp/generator}/xcode_ninja.py (98%) rename tools/gyp/{pylib/gyp => gyp/generator}/xcodeproj_file.py (98%) rename tools/gyp/{pylib => }/gyp/input.py (75%) create mode 100644 tools/gyp/gyp/lib/__init__.py rename tools/gyp/{pylib/gyp => gyp/lib}/ninja_syntax.py (100%) rename tools/gyp/{pylib/gyp => gyp/lib}/simple_copy.py (63%) rename tools/gyp/{pylib => }/gyp/msvs_emulation.py (67%) rename tools/gyp/{pylib/gyp => gyp/unit_tests}/MSVSSettings_test.py (81%) mode change 100755 => 100644 create mode 100644 tools/gyp/gyp/unit_tests/NinjaWriter_test.py create mode 100644 tools/gyp/gyp/unit_tests/__init__.py rename tools/gyp/{pylib/gyp => gyp/unit_tests}/common_test.py (97%) mode change 100755 => 100644 rename tools/gyp/{pylib/gyp => gyp/unit_tests}/easy_xml_test.py (98%) mode change 100755 => 100644 rename tools/gyp/{pylib/gyp/generator/msvs_test.py => gyp/unit_tests/generator_msvs_test.py} (94%) mode change 100755 => 100644 rename tools/gyp/{pylib/gyp/generator/xcode_test.py => gyp/unit_tests/generator_xcode_test.py} (100%) rename tools/gyp/{pylib/gyp => gyp/unit_tests}/input_test.py (81%) mode change 100755 => 100644 rename tools/gyp/{pylib => }/gyp/xcode_emulation.py (95%) delete mode 100644 tools/gyp/pylib/gyp/MSVSProject.py delete mode 100644 tools/gyp/pylib/gyp/MSVSUserFile.py delete mode 100644 tools/gyp/pylib/gyp/MSVSUtil.py delete mode 100644 tools/gyp/pylib/gyp/MSVSVersion.py delete mode 100644 tools/gyp/pylib/gyp/generator/compile_commands_json.py delete mode 100644 tools/gyp/pylib/gyp/generator/ninja.py delete mode 100644 tools/gyp/pylib/gyp/generator/ninja_test.py delete mode 100644 tools/gyp/pylib/gyp/ordered_dict.py delete mode 100644 tools/gyp/pylib/gyp/xml_fix.py delete mode 100755 tools/gyp/samples/samples delete mode 100644 tools/gyp/samples/samples.bat create mode 100644 tools/gyp/setup.cfg delete mode 100755 tools/gyp/setup.py create mode 100644 tools/gyp/test/actions/bare/gyptest-bare.py create mode 100644 tools/gyp/test/actions/bare/src/bare.gyp create mode 100644 tools/gyp/test/actions/bare/src/bare.py create mode 100644 tools/gyp/test/actions/depfile/depfile.gyp create mode 100644 tools/gyp/test/actions/depfile/gyptest-all.py create mode 100644 tools/gyp/test/actions/depfile/input.txt create mode 100644 tools/gyp/test/actions/e2e/generated-header/action.py create mode 100644 tools/gyp/test/actions/e2e/generated-header/main.cc create mode 100644 tools/gyp/test/actions/e2e/generated-header/test.gyp create mode 100644 tools/gyp/test/actions/e2e/gyptest-all.py create mode 100644 tools/gyp/test/actions/e2e/gyptest-default.py create mode 100644 tools/gyp/test/actions/e2e/gyptest-errors.py create mode 100644 tools/gyp/test/actions/e2e/gyptest-generated-header.py create mode 100644 tools/gyp/test/actions/e2e/src/action_missing_name.gyp create mode 100644 tools/gyp/test/actions/e2e/src/actions.gyp create mode 100644 tools/gyp/test/actions/e2e/src/confirm-dep-files.py create mode 100644 tools/gyp/test/actions/e2e/src/subdir1/counter.py create mode 100644 tools/gyp/test/actions/e2e/src/subdir1/executable.gyp create mode 100644 tools/gyp/test/actions/e2e/src/subdir1/make-prog1.py create mode 100644 tools/gyp/test/actions/e2e/src/subdir1/make-prog2.py create mode 100644 tools/gyp/test/actions/e2e/src/subdir1/program.c create mode 100644 tools/gyp/test/actions/e2e/src/subdir2/make-file.py create mode 100644 tools/gyp/test/actions/e2e/src/subdir2/none.gyp create mode 100644 tools/gyp/test/actions/e2e/src/subdir3/generate_main.py create mode 100644 tools/gyp/test/actions/e2e/src/subdir3/null_input.gyp create mode 100644 tools/gyp/test/actions/multiple-outputs-with-dependencies/gyptest-action.py create mode 100644 tools/gyp/test/actions/multiple-outputs-with-dependencies/src/action.gyp create mode 100644 tools/gyp/test/actions/multiple-outputs-with-dependencies/src/rcopy.py create mode 100644 tools/gyp/test/actions/multiple-outputs/gyptest-multiple-outputs.py create mode 100644 tools/gyp/test/actions/multiple-outputs/src/multiple-outputs.gyp create mode 100644 tools/gyp/test/actions/multiple-outputs/src/touch.py create mode 100644 tools/gyp/test/actions/multiple/gyptest-all.py create mode 100644 tools/gyp/test/actions/multiple/src/actions.gyp create mode 100644 tools/gyp/test/actions/multiple/src/copyfile.py create mode 100644 tools/gyp/test/actions/multiple/src/filter.py create mode 100644 tools/gyp/test/actions/multiple/src/foo.c create mode 100644 tools/gyp/test/actions/multiple/src/input.txt create mode 100644 tools/gyp/test/actions/multiple/src/main.c create mode 100644 tools/gyp/test/actions/none/gyptest-none.py create mode 100644 tools/gyp/test/actions/none/src/fake_cross.py create mode 100644 tools/gyp/test/actions/none/src/foo.cc create mode 100644 tools/gyp/test/actions/none/src/none_with_source_files.gyp create mode 100644 tools/gyp/test/actions/subdir/gyptest-action.py create mode 100644 tools/gyp/test/actions/subdir/src/make-file.py create mode 100644 tools/gyp/test/actions/subdir/src/none.gyp create mode 100644 tools/gyp/test/actions/subdir/src/subdir/make-subdir-file.py create mode 100644 tools/gyp/test/actions/subdir/src/subdir/subdir.gyp create mode 100644 tools/gyp/test/additional-targets/gyptest-additional.py create mode 100644 tools/gyp/test/additional-targets/src/all.gyp create mode 100644 tools/gyp/test/additional-targets/src/dir1/actions.gyp create mode 100644 tools/gyp/test/additional-targets/src/dir1/emit.py create mode 100644 tools/gyp/test/additional-targets/src/dir1/lib1.c create mode 100644 tools/gyp/test/analyzer/common.gypi create mode 100644 tools/gyp/test/analyzer/gyptest-analyzer.py create mode 100644 tools/gyp/test/analyzer/static_library_test.gyp create mode 100644 tools/gyp/test/analyzer/subdir/subdir.gyp create mode 100644 tools/gyp/test/analyzer/subdir/subdir2/subdir2.gyp create mode 100644 tools/gyp/test/analyzer/subdir2/subdir.gyp create mode 100644 tools/gyp/test/analyzer/subdir2/subdir.includes.gypi create mode 100644 tools/gyp/test/analyzer/test.gyp create mode 100644 tools/gyp/test/analyzer/test2.gyp create mode 100644 tools/gyp/test/analyzer/test2.includes.gypi create mode 100644 tools/gyp/test/analyzer/test2.includes.includes.gypi create mode 100644 tools/gyp/test/analyzer/test2.toplevel_includes.gypi create mode 100644 tools/gyp/test/analyzer/test3.gyp create mode 100644 tools/gyp/test/analyzer/test4.gyp create mode 100644 tools/gyp/test/analyzer/test5.gyp create mode 100644 tools/gyp/test/arflags/gyptest-arflags.py create mode 100644 tools/gyp/test/arflags/lib.cc create mode 100644 tools/gyp/test/arflags/test.gyp create mode 100644 tools/gyp/test/assembly/gyptest-assembly.py create mode 100644 tools/gyp/test/assembly/gyptest-override.py create mode 100644 tools/gyp/test/assembly/src/as.bat create mode 100644 tools/gyp/test/assembly/src/assembly.gyp create mode 100644 tools/gyp/test/assembly/src/lib1.S create mode 100644 tools/gyp/test/assembly/src/lib1.c create mode 100644 tools/gyp/test/assembly/src/override.gyp create mode 100644 tools/gyp/test/assembly/src/override_asm.asm create mode 100644 tools/gyp/test/assembly/src/program.c create mode 100644 tools/gyp/test/build-option/gyptest-build.py create mode 100644 tools/gyp/test/build-option/hello.c create mode 100644 tools/gyp/test/build-option/hello.gyp create mode 100644 tools/gyp/test/builddir/gyptest-all.py create mode 100644 tools/gyp/test/builddir/gyptest-default.py create mode 100644 tools/gyp/test/builddir/src/builddir.gypi create mode 100644 tools/gyp/test/builddir/src/func1.c create mode 100644 tools/gyp/test/builddir/src/func2.c create mode 100644 tools/gyp/test/builddir/src/func3.c create mode 100644 tools/gyp/test/builddir/src/func4.c create mode 100644 tools/gyp/test/builddir/src/func5.c create mode 100644 tools/gyp/test/builddir/src/prog1.c create mode 100644 tools/gyp/test/builddir/src/prog1.gyp create mode 100644 tools/gyp/test/builddir/src/subdir2/prog2.c create mode 100644 tools/gyp/test/builddir/src/subdir2/prog2.gyp create mode 100644 tools/gyp/test/builddir/src/subdir2/subdir3/prog3.c create mode 100644 tools/gyp/test/builddir/src/subdir2/subdir3/prog3.gyp create mode 100644 tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.c create mode 100644 tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.gyp create mode 100644 tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.c create mode 100644 tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.gyp create mode 100644 tools/gyp/test/cflags/cflags.c create mode 100644 tools/gyp/test/cflags/cflags.gyp create mode 100644 tools/gyp/test/cflags/gyptest-cflags.py create mode 100644 tools/gyp/test/compilable/gyptest-headers.py create mode 100644 tools/gyp/test/compilable/src/headers.gyp create mode 100644 tools/gyp/test/compilable/src/lib1.cpp create mode 100644 tools/gyp/test/compilable/src/lib1.hpp create mode 100644 tools/gyp/test/compilable/src/program.cpp create mode 100644 tools/gyp/test/compiler-override/compiler-exe.gyp create mode 100644 tools/gyp/test/compiler-override/compiler-global-settings.gyp.in create mode 100644 tools/gyp/test/compiler-override/compiler-host.gyp create mode 100644 tools/gyp/test/compiler-override/compiler-shared-lib.gyp create mode 100644 tools/gyp/test/compiler-override/cxxtest.cc create mode 100644 tools/gyp/test/compiler-override/gyptest-compiler-env-toolchain.py create mode 100644 tools/gyp/test/compiler-override/gyptest-compiler-env.py create mode 100644 tools/gyp/test/compiler-override/gyptest-compiler-global-settings.py create mode 100644 tools/gyp/test/compiler-override/my_cc.py create mode 100644 tools/gyp/test/compiler-override/my_cxx.py create mode 100644 tools/gyp/test/compiler-override/my_ld.py create mode 100644 tools/gyp/test/compiler-override/my_nm.py create mode 100644 tools/gyp/test/compiler-override/my_readelf.py create mode 100644 tools/gyp/test/compiler-override/test.c create mode 100644 tools/gyp/test/conditions/elseif/elseif.gyp create mode 100644 tools/gyp/test/conditions/elseif/elseif_bad1.gyp create mode 100644 tools/gyp/test/conditions/elseif/elseif_bad2.gyp create mode 100644 tools/gyp/test/conditions/elseif/elseif_bad3.gyp create mode 100644 tools/gyp/test/conditions/elseif/elseif_conditions.gypi create mode 100644 tools/gyp/test/conditions/elseif/gyptest_elseif.py create mode 100644 tools/gyp/test/conditions/elseif/program.cc create mode 100644 tools/gyp/test/configurations/basics/configurations.c create mode 100644 tools/gyp/test/configurations/basics/configurations.gyp create mode 100644 tools/gyp/test/configurations/basics/gyptest-configurations.py create mode 100644 tools/gyp/test/configurations/inheritance/configurations.c create mode 100644 tools/gyp/test/configurations/inheritance/configurations.gyp create mode 100644 tools/gyp/test/configurations/inheritance/duplicates.gyp create mode 100644 tools/gyp/test/configurations/inheritance/duplicates.gypd.golden create mode 100644 tools/gyp/test/configurations/inheritance/gyptest-duplicates.py create mode 100644 tools/gyp/test/configurations/inheritance/gyptest-inheritance.py create mode 100644 tools/gyp/test/configurations/invalid/actions.gyp create mode 100644 tools/gyp/test/configurations/invalid/all_dependent_settings.gyp create mode 100644 tools/gyp/test/configurations/invalid/configurations.gyp create mode 100644 tools/gyp/test/configurations/invalid/dependencies.gyp create mode 100644 tools/gyp/test/configurations/invalid/direct_dependent_settings.gyp create mode 100644 tools/gyp/test/configurations/invalid/gyptest-configurations.py create mode 100644 tools/gyp/test/configurations/invalid/libraries.gyp create mode 100644 tools/gyp/test/configurations/invalid/link_settings.gyp create mode 100644 tools/gyp/test/configurations/invalid/sources.gyp create mode 100644 tools/gyp/test/configurations/invalid/standalone_static_library.gyp create mode 100644 tools/gyp/test/configurations/invalid/target_name.gyp create mode 100644 tools/gyp/test/configurations/invalid/type.gyp create mode 100644 tools/gyp/test/configurations/target_platform/configurations.gyp create mode 100644 tools/gyp/test/configurations/target_platform/front.c create mode 100644 tools/gyp/test/configurations/target_platform/gyptest-target_platform.py create mode 100644 tools/gyp/test/configurations/target_platform/left.c create mode 100644 tools/gyp/test/configurations/target_platform/right.c create mode 100644 tools/gyp/test/configurations/x64/configurations.c create mode 100644 tools/gyp/test/configurations/x64/configurations.gyp create mode 100644 tools/gyp/test/configurations/x64/gyptest-x86.py create mode 100644 tools/gyp/test/copies/gyptest-all.py create mode 100644 tools/gyp/test/copies/gyptest-attribs.py create mode 100644 tools/gyp/test/copies/gyptest-default.py create mode 100644 tools/gyp/test/copies/gyptest-samedir.py create mode 100644 tools/gyp/test/copies/gyptest-slash.py create mode 100644 tools/gyp/test/copies/gyptest-sourceless-shared-lib.py create mode 100644 tools/gyp/test/copies/gyptest-updir.py create mode 100644 tools/gyp/test/copies/src/copies-attribs.gyp create mode 100644 tools/gyp/test/copies/src/copies-samedir.gyp create mode 100644 tools/gyp/test/copies/src/copies-slash.gyp create mode 100644 tools/gyp/test/copies/src/copies-sourceless-shared-lib.gyp create mode 100644 tools/gyp/test/copies/src/copies-updir.gyp create mode 100644 tools/gyp/test/copies/src/copies.gyp create mode 100644 tools/gyp/test/copies/src/directory/file3 create mode 100644 tools/gyp/test/copies/src/directory/file4 create mode 100644 tools/gyp/test/copies/src/directory/subdir/file5 create mode 100644 tools/gyp/test/copies/src/executable-file.sh create mode 100644 tools/gyp/test/copies/src/file1 create mode 100644 tools/gyp/test/copies/src/file2 create mode 100644 tools/gyp/test/copies/src/foo.c create mode 100644 tools/gyp/test/copies/src/parentdir/subdir/file6 create mode 100644 tools/gyp/test/custom-generator/gyptest-custom-generator.py create mode 100644 tools/gyp/test/custom-generator/mygenerator.py create mode 100644 tools/gyp/test/custom-generator/test.gyp create mode 100644 tools/gyp/test/cxxflags/cxxflags.cc create mode 100644 tools/gyp/test/cxxflags/cxxflags.gyp create mode 100644 tools/gyp/test/cxxflags/gyptest-cxxflags.py create mode 100644 tools/gyp/test/defines-escaping/defines-escaping.c create mode 100644 tools/gyp/test/defines-escaping/defines-escaping.gyp create mode 100644 tools/gyp/test/defines-escaping/gyptest-defines-escaping.py create mode 100644 tools/gyp/test/defines/defines-env.gyp create mode 100644 tools/gyp/test/defines/defines.c create mode 100644 tools/gyp/test/defines/defines.gyp create mode 100644 tools/gyp/test/defines/gyptest-define-override.py create mode 100644 tools/gyp/test/defines/gyptest-defines-env-regyp.py create mode 100644 tools/gyp/test/defines/gyptest-defines-env.py create mode 100644 tools/gyp/test/defines/gyptest-defines.py create mode 100644 tools/gyp/test/dependencies/a.c create mode 100644 tools/gyp/test/dependencies/adso/all_dependent_settings_order.gyp create mode 100644 tools/gyp/test/dependencies/adso/write_args.py create mode 100644 tools/gyp/test/dependencies/b/b.c create mode 100644 tools/gyp/test/dependencies/b/b.gyp create mode 100644 tools/gyp/test/dependencies/b/b3.c create mode 100644 tools/gyp/test/dependencies/c/c.c create mode 100644 tools/gyp/test/dependencies/c/c.gyp create mode 100644 tools/gyp/test/dependencies/c/d.c create mode 100644 tools/gyp/test/dependencies/double_dependency.gyp create mode 100644 tools/gyp/test/dependencies/double_dependent.gyp create mode 100644 tools/gyp/test/dependencies/extra_targets.gyp create mode 100644 tools/gyp/test/dependencies/gyptest-all-dependent-settings-order.py create mode 100644 tools/gyp/test/dependencies/gyptest-double-dependency.py create mode 100644 tools/gyp/test/dependencies/gyptest-extra-targets.py create mode 100644 tools/gyp/test/dependencies/gyptest-indirect-module-dependency.py create mode 100644 tools/gyp/test/dependencies/gyptest-lib-only.py create mode 100644 tools/gyp/test/dependencies/gyptest-none-traversal.py create mode 100644 tools/gyp/test/dependencies/gyptest-sharedlib-linksettings.py create mode 100644 tools/gyp/test/dependencies/lib_only.gyp create mode 100644 tools/gyp/test/dependencies/main.c create mode 100644 tools/gyp/test/dependencies/module-dep/a.cc create mode 100644 tools/gyp/test/dependencies/module-dep/dll.cc create mode 100644 tools/gyp/test/dependencies/module-dep/exe.cc create mode 100644 tools/gyp/test/dependencies/module-dep/indirect-module-dependency.gyp create mode 100644 tools/gyp/test/dependencies/none_traversal.gyp create mode 100644 tools/gyp/test/dependencies/sharedlib-linksettings/program.c create mode 100644 tools/gyp/test/dependencies/sharedlib-linksettings/sharedlib.c create mode 100644 tools/gyp/test/dependencies/sharedlib-linksettings/staticlib.c create mode 100644 tools/gyp/test/dependencies/sharedlib-linksettings/test.gyp create mode 100644 tools/gyp/test/dependency-copy/gyptest-copy.py create mode 100644 tools/gyp/test/dependency-copy/src/copies.gyp create mode 100644 tools/gyp/test/dependency-copy/src/file1.c create mode 100644 tools/gyp/test/dependency-copy/src/file2.c create mode 100644 tools/gyp/test/determinism/determinism.gyp create mode 100644 tools/gyp/test/determinism/empty-targets.gyp create mode 100644 tools/gyp/test/determinism/gyptest-determinism.py create mode 100644 tools/gyp/test/determinism/gyptest-empty-target-names.py create mode 100644 tools/gyp/test/determinism/gyptest-needed-variables.py create mode 100644 tools/gyp/test/determinism/gyptest-solibs.py create mode 100644 tools/gyp/test/determinism/main.cc create mode 100644 tools/gyp/test/determinism/needed-variables.gyp create mode 100644 tools/gyp/test/determinism/rule.py create mode 100644 tools/gyp/test/determinism/solib.cc create mode 100644 tools/gyp/test/determinism/solibs.gyp create mode 100644 tools/gyp/test/empty-target/empty-target.gyp create mode 100644 tools/gyp/test/empty-target/gyptest-empty-target.py create mode 100644 tools/gyp/test/errors/dependency_cycle.gyp create mode 100644 tools/gyp/test/errors/duplicate_basenames.gyp create mode 100644 tools/gyp/test/errors/duplicate_node.gyp create mode 100644 tools/gyp/test/errors/duplicate_rule.gyp create mode 100644 tools/gyp/test/errors/duplicate_targets.gyp create mode 100644 tools/gyp/test/errors/error_command.gyp create mode 100644 tools/gyp/test/errors/file_cycle0.gyp create mode 100644 tools/gyp/test/errors/file_cycle1.gyp create mode 100644 tools/gyp/test/errors/gyptest-errors.py create mode 100644 tools/gyp/test/errors/missing_command.gyp create mode 100644 tools/gyp/test/errors/missing_dep.gyp create mode 100644 tools/gyp/test/errors/missing_targets.gyp create mode 100644 tools/gyp/test/escaping/colon/test.gyp create mode 100644 tools/gyp/test/escaping/gyptest-colon.py create mode 100644 tools/gyp/test/exclusion/exclusion.gyp create mode 100644 tools/gyp/test/exclusion/gyptest-exclusion.py create mode 100644 tools/gyp/test/exclusion/hello.c create mode 100644 tools/gyp/test/external-cross-compile/gyptest-cross.py create mode 100644 tools/gyp/test/external-cross-compile/src/bogus1.cc create mode 100644 tools/gyp/test/external-cross-compile/src/bogus2.c create mode 100644 tools/gyp/test/external-cross-compile/src/cross.gyp create mode 100644 tools/gyp/test/external-cross-compile/src/cross_compile.gypi create mode 100644 tools/gyp/test/external-cross-compile/src/fake_cross.py create mode 100644 tools/gyp/test/external-cross-compile/src/program.cc create mode 100644 tools/gyp/test/external-cross-compile/src/test1.cc create mode 100644 tools/gyp/test/external-cross-compile/src/test2.c create mode 100644 tools/gyp/test/external-cross-compile/src/test3.cc create mode 100644 tools/gyp/test/external-cross-compile/src/test4.c create mode 100644 tools/gyp/test/external-cross-compile/src/tochar.py create mode 100644 tools/gyp/test/fixtures/test-charmap.py create mode 100644 tools/gyp/test/generator-output/actions/actions.gyp create mode 100644 tools/gyp/test/generator-output/actions/build/README.txt create mode 100644 tools/gyp/test/generator-output/actions/subdir1/actions-out/README.txt create mode 100644 tools/gyp/test/generator-output/actions/subdir1/build/README.txt create mode 100644 tools/gyp/test/generator-output/actions/subdir1/executable.gyp create mode 100644 tools/gyp/test/generator-output/actions/subdir1/make-prog1.py create mode 100644 tools/gyp/test/generator-output/actions/subdir1/make-prog2.py create mode 100644 tools/gyp/test/generator-output/actions/subdir1/program.c create mode 100644 tools/gyp/test/generator-output/actions/subdir2/actions-out/README.txt create mode 100644 tools/gyp/test/generator-output/actions/subdir2/build/README.txt create mode 100644 tools/gyp/test/generator-output/actions/subdir2/make-file.py create mode 100644 tools/gyp/test/generator-output/actions/subdir2/none.gyp create mode 100644 tools/gyp/test/generator-output/copies/build/README.txt create mode 100644 tools/gyp/test/generator-output/copies/copies-out/README.txt create mode 100644 tools/gyp/test/generator-output/copies/copies.gyp create mode 100644 tools/gyp/test/generator-output/copies/file1 create mode 100644 tools/gyp/test/generator-output/copies/file2 create mode 100644 tools/gyp/test/generator-output/copies/subdir/build/README.txt create mode 100644 tools/gyp/test/generator-output/copies/subdir/copies-out/README.txt create mode 100644 tools/gyp/test/generator-output/copies/subdir/file3 create mode 100644 tools/gyp/test/generator-output/copies/subdir/file4 create mode 100644 tools/gyp/test/generator-output/copies/subdir/subdir.gyp create mode 100644 tools/gyp/test/generator-output/gyptest-actions.py create mode 100644 tools/gyp/test/generator-output/gyptest-copies.py create mode 100644 tools/gyp/test/generator-output/gyptest-depth.py create mode 100644 tools/gyp/test/generator-output/gyptest-mac-bundle.py create mode 100644 tools/gyp/test/generator-output/gyptest-relocate.py create mode 100644 tools/gyp/test/generator-output/gyptest-rules.py create mode 100644 tools/gyp/test/generator-output/gyptest-subdir2-deep.py create mode 100644 tools/gyp/test/generator-output/gyptest-symlink.py create mode 100644 tools/gyp/test/generator-output/gyptest-top-all.py create mode 100644 tools/gyp/test/generator-output/mac-bundle/Info.plist create mode 100644 tools/gyp/test/generator-output/mac-bundle/app.order create mode 100644 tools/gyp/test/generator-output/mac-bundle/header.h create mode 100644 tools/gyp/test/generator-output/mac-bundle/main.c create mode 100644 tools/gyp/test/generator-output/mac-bundle/resource.sb create mode 100644 tools/gyp/test/generator-output/mac-bundle/test.gyp create mode 100644 tools/gyp/test/generator-output/rules/build/README.txt create mode 100644 tools/gyp/test/generator-output/rules/copy-file.py create mode 100644 tools/gyp/test/generator-output/rules/rules.gyp create mode 100644 tools/gyp/test/generator-output/rules/subdir1/build/README.txt create mode 100644 tools/gyp/test/generator-output/rules/subdir1/define3.in0 create mode 100644 tools/gyp/test/generator-output/rules/subdir1/define4.in0 create mode 100644 tools/gyp/test/generator-output/rules/subdir1/executable.gyp create mode 100644 tools/gyp/test/generator-output/rules/subdir1/function1.in1 create mode 100644 tools/gyp/test/generator-output/rules/subdir1/function2.in1 create mode 100644 tools/gyp/test/generator-output/rules/subdir1/program.c create mode 100644 tools/gyp/test/generator-output/rules/subdir2/build/README.txt create mode 100644 tools/gyp/test/generator-output/rules/subdir2/file1.in0 create mode 100644 tools/gyp/test/generator-output/rules/subdir2/file2.in0 create mode 100644 tools/gyp/test/generator-output/rules/subdir2/file3.in1 create mode 100644 tools/gyp/test/generator-output/rules/subdir2/file4.in1 create mode 100644 tools/gyp/test/generator-output/rules/subdir2/none.gyp create mode 100644 tools/gyp/test/generator-output/rules/subdir2/rules-out/README.txt create mode 100644 tools/gyp/test/generator-output/src/build/README.txt create mode 100644 tools/gyp/test/generator-output/src/inc.h create mode 100644 tools/gyp/test/generator-output/src/inc1/include1.h create mode 100644 tools/gyp/test/generator-output/src/prog1.c create mode 100644 tools/gyp/test/generator-output/src/prog1.gyp create mode 100644 tools/gyp/test/generator-output/src/subdir2/build/README.txt create mode 100644 tools/gyp/test/generator-output/src/subdir2/deeper/build/README.txt create mode 100644 tools/gyp/test/generator-output/src/subdir2/deeper/deeper.c create mode 100644 tools/gyp/test/generator-output/src/subdir2/deeper/deeper.gyp create mode 100644 tools/gyp/test/generator-output/src/subdir2/deeper/deeper.h create mode 100644 tools/gyp/test/generator-output/src/subdir2/inc2/include2.h create mode 100644 tools/gyp/test/generator-output/src/subdir2/prog2.c create mode 100644 tools/gyp/test/generator-output/src/subdir2/prog2.gyp create mode 100644 tools/gyp/test/generator-output/src/subdir3/build/README.txt create mode 100644 tools/gyp/test/generator-output/src/subdir3/inc3/include3.h create mode 100644 tools/gyp/test/generator-output/src/subdir3/prog3.c create mode 100644 tools/gyp/test/generator-output/src/subdir3/prog3.gyp create mode 100644 tools/gyp/test/generator-output/src/symroot.gypi create mode 100644 tools/gyp/test/gyp-defines/defines.gyp create mode 100644 tools/gyp/test/gyp-defines/echo.py create mode 100644 tools/gyp/test/gyp-defines/gyptest-multiple-values.py create mode 100644 tools/gyp/test/gyp-defines/gyptest-regyp.py create mode 100644 tools/gyp/test/hard_dependency/gyptest-exported-hard-dependency.py create mode 100644 tools/gyp/test/hard_dependency/gyptest-no-exported-hard-dependency.py create mode 100644 tools/gyp/test/hard_dependency/src/a.c create mode 100644 tools/gyp/test/hard_dependency/src/a.h create mode 100644 tools/gyp/test/hard_dependency/src/b.c create mode 100644 tools/gyp/test/hard_dependency/src/b.h create mode 100644 tools/gyp/test/hard_dependency/src/c.c create mode 100644 tools/gyp/test/hard_dependency/src/c.h create mode 100644 tools/gyp/test/hard_dependency/src/d.c create mode 100644 tools/gyp/test/hard_dependency/src/emit.py create mode 100644 tools/gyp/test/hard_dependency/src/hard_dependency.gyp create mode 100644 tools/gyp/test/hello/gyptest-all.py create mode 100644 tools/gyp/test/hello/gyptest-default.py create mode 100644 tools/gyp/test/hello/gyptest-disable-regyp.py create mode 100644 tools/gyp/test/hello/gyptest-regyp-output.py create mode 100644 tools/gyp/test/hello/gyptest-regyp.py create mode 100644 tools/gyp/test/hello/gyptest-target.py create mode 100644 tools/gyp/test/hello/hello.c create mode 100644 tools/gyp/test/hello/hello.gyp create mode 100644 tools/gyp/test/hello/hello2.c create mode 100644 tools/gyp/test/hello/hello2.gyp create mode 100644 tools/gyp/test/home_dot_gyp/gyptest-home-includes-config-arg.py create mode 100644 tools/gyp/test/home_dot_gyp/gyptest-home-includes-config-env.py create mode 100644 tools/gyp/test/home_dot_gyp/gyptest-home-includes-regyp.py create mode 100644 tools/gyp/test/home_dot_gyp/gyptest-home-includes.py create mode 100644 tools/gyp/test/home_dot_gyp/src/all.gyp create mode 100644 tools/gyp/test/home_dot_gyp/src/printfoo.c create mode 100644 tools/gyp/test/include_dirs/gyptest-all.py create mode 100644 tools/gyp/test/include_dirs/gyptest-default.py create mode 100644 tools/gyp/test/include_dirs/src/inc.h create mode 100644 tools/gyp/test/include_dirs/src/inc1/include1.h create mode 100644 tools/gyp/test/include_dirs/src/includes.c create mode 100644 tools/gyp/test/include_dirs/src/includes.gyp create mode 100644 tools/gyp/test/include_dirs/src/shadow1/shadow.h create mode 100644 tools/gyp/test/include_dirs/src/shadow2/shadow.h create mode 100644 tools/gyp/test/include_dirs/src/subdir/inc.h create mode 100644 tools/gyp/test/include_dirs/src/subdir/inc2/include2.h create mode 100644 tools/gyp/test/include_dirs/src/subdir/subdir_includes.c create mode 100644 tools/gyp/test/include_dirs/src/subdir/subdir_includes.gyp create mode 100644 tools/gyp/test/intermediate_dir/gyptest-intermediate-dir.py create mode 100644 tools/gyp/test/intermediate_dir/src/script.py create mode 100644 tools/gyp/test/intermediate_dir/src/shared_infile.txt create mode 100644 tools/gyp/test/intermediate_dir/src/test.gyp create mode 100644 tools/gyp/test/intermediate_dir/src/test2.gyp create mode 100644 tools/gyp/test/ios/app-bundle/TestApp/English.lproj/InfoPlist-error.strings create mode 100644 tools/gyp/test/ios/app-bundle/TestApp/English.lproj/InfoPlist.strings create mode 100644 tools/gyp/test/ios/app-bundle/TestApp/English.lproj/LanguageMap.plist create mode 100644 tools/gyp/test/ios/app-bundle/TestApp/English.lproj/MainMenu.xib create mode 100644 tools/gyp/test/ios/app-bundle/TestApp/English.lproj/Main_iPhone.storyboard create mode 100644 tools/gyp/test/ios/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 tools/gyp/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json create mode 100644 tools/gyp/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png create mode 100644 tools/gyp/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png create mode 100644 tools/gyp/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png create mode 100644 tools/gyp/test/ios/app-bundle/TestApp/TestApp-Info.plist create mode 100644 tools/gyp/test/ios/app-bundle/TestApp/check_no_signature.py create mode 100644 tools/gyp/test/ios/app-bundle/TestApp/main.m create mode 100644 tools/gyp/test/ios/app-bundle/TestApp/only-compile-in-32-bits.m create mode 100644 tools/gyp/test/ios/app-bundle/TestApp/only-compile-in-64-bits.m create mode 100644 tools/gyp/test/ios/app-bundle/test-archs.gyp create mode 100644 tools/gyp/test/ios/app-bundle/test-assets-catalog.gyp create mode 100644 tools/gyp/test/ios/app-bundle/test-crosscompile.gyp create mode 100644 tools/gyp/test/ios/app-bundle/test-device.gyp create mode 100644 tools/gyp/test/ios/app-bundle/test.gyp create mode 100644 tools/gyp/test/ios/app-bundle/tool_main.cc create mode 100644 tools/gyp/test/ios/copies-with-xcode-envvars/Info.plist create mode 100644 tools/gyp/test/ios/copies-with-xcode-envvars/copies-with-xcode-envvars.gyp create mode 100644 tools/gyp/test/ios/copies-with-xcode-envvars/empty.c create mode 100644 tools/gyp/test/ios/copies-with-xcode-envvars/file0 create mode 100644 tools/gyp/test/ios/copies-with-xcode-envvars/file1 create mode 100644 tools/gyp/test/ios/copies-with-xcode-envvars/file10 create mode 100644 tools/gyp/test/ios/copies-with-xcode-envvars/file11 create mode 100644 tools/gyp/test/ios/copies-with-xcode-envvars/file2 create mode 100644 tools/gyp/test/ios/copies-with-xcode-envvars/file3 create mode 100644 tools/gyp/test/ios/copies-with-xcode-envvars/file4 create mode 100644 tools/gyp/test/ios/copies-with-xcode-envvars/file5 create mode 100644 tools/gyp/test/ios/copies-with-xcode-envvars/file6 create mode 100644 tools/gyp/test/ios/copies-with-xcode-envvars/file7 create mode 100644 tools/gyp/test/ios/copies-with-xcode-envvars/file8 create mode 100644 tools/gyp/test/ios/copies-with-xcode-envvars/file9 create mode 100644 tools/gyp/test/ios/deployment-target/check-version-min.c create mode 100644 tools/gyp/test/ios/deployment-target/deployment-target.gyp create mode 100644 tools/gyp/test/ios/extension/ActionExtension/ActionViewController.h create mode 100644 tools/gyp/test/ios/extension/ActionExtension/ActionViewController.m create mode 100644 tools/gyp/test/ios/extension/ActionExtension/Info.plist create mode 100644 tools/gyp/test/ios/extension/ActionExtension/MainInterface.storyboard create mode 100644 tools/gyp/test/ios/extension/ExtensionContainer/AppDelegate.h create mode 100644 tools/gyp/test/ios/extension/ExtensionContainer/AppDelegate.m create mode 100644 tools/gyp/test/ios/extension/ExtensionContainer/Base.lproj/Main.storyboard create mode 100644 tools/gyp/test/ios/extension/ExtensionContainer/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 tools/gyp/test/ios/extension/ExtensionContainer/Images.xcassets/LaunchImage.launchimage/Contents.json create mode 100644 tools/gyp/test/ios/extension/ExtensionContainer/Info.plist create mode 100644 tools/gyp/test/ios/extension/ExtensionContainer/ViewController.h create mode 100644 tools/gyp/test/ios/extension/ExtensionContainer/ViewController.m create mode 100644 tools/gyp/test/ios/extension/ExtensionContainer/main.m create mode 100644 tools/gyp/test/ios/extension/extension.gyp create mode 100644 tools/gyp/test/ios/framework/framework.gyp create mode 100644 tools/gyp/test/ios/framework/iOSFramework/Info.plist create mode 100644 tools/gyp/test/ios/framework/iOSFramework/Thing.h create mode 100644 tools/gyp/test/ios/framework/iOSFramework/Thing.m create mode 100644 tools/gyp/test/ios/framework/iOSFramework/iOSFramework.h create mode 100644 tools/gyp/test/ios/gyptest-app-ios-assets-catalog.py create mode 100644 tools/gyp/test/ios/gyptest-app-ios.py create mode 100644 tools/gyp/test/ios/gyptest-archs.py create mode 100644 tools/gyp/test/ios/gyptest-copies-with-xcode-envvars.py create mode 100644 tools/gyp/test/ios/gyptest-crosscompile.py create mode 100644 tools/gyp/test/ios/gyptest-deployment-target.py create mode 100644 tools/gyp/test/ios/gyptest-extension.py create mode 100644 tools/gyp/test/ios/gyptest-framework.py create mode 100644 tools/gyp/test/ios/gyptest-per-config-settings.py create mode 100644 tools/gyp/test/ios/gyptest-watch.py create mode 100644 tools/gyp/test/ios/gyptest-xcode-ninja.py create mode 100644 tools/gyp/test/ios/watch/WatchApp/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 tools/gyp/test/ios/watch/WatchApp/Images.xcassets/LaunchImage.launchimage/Contents.json create mode 100644 tools/gyp/test/ios/watch/WatchApp/Info.plist create mode 100644 tools/gyp/test/ios/watch/WatchApp/Interface.storyboard create mode 100644 tools/gyp/test/ios/watch/WatchContainer/AppDelegate.h create mode 100644 tools/gyp/test/ios/watch/WatchContainer/AppDelegate.m create mode 100644 tools/gyp/test/ios/watch/WatchContainer/Base.lproj/Main.storyboard create mode 100644 tools/gyp/test/ios/watch/WatchContainer/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 tools/gyp/test/ios/watch/WatchContainer/Images.xcassets/LaunchImage.launchimage/Contents.json create mode 100644 tools/gyp/test/ios/watch/WatchContainer/Info.plist create mode 100644 tools/gyp/test/ios/watch/WatchContainer/ViewController.h create mode 100644 tools/gyp/test/ios/watch/WatchContainer/ViewController.m create mode 100644 tools/gyp/test/ios/watch/WatchContainer/main.m create mode 100644 tools/gyp/test/ios/watch/WatchKitExtension/Images.xcassets/MyImage.imageset/Contents.json create mode 100644 tools/gyp/test/ios/watch/WatchKitExtension/Info.plist create mode 100644 tools/gyp/test/ios/watch/WatchKitExtension/InterfaceController.h create mode 100644 tools/gyp/test/ios/watch/WatchKitExtension/InterfaceController.m create mode 100644 tools/gyp/test/ios/watch/WatchKitExtension/MainInterface.storyboard create mode 100644 tools/gyp/test/ios/watch/watch.gyp create mode 100644 tools/gyp/test/ios/xctests/App/AppDelegate.h create mode 100644 tools/gyp/test/ios/xctests/App/AppDelegate.m create mode 100644 tools/gyp/test/ios/xctests/App/Base.lproj/LaunchScreen.xib create mode 100644 tools/gyp/test/ios/xctests/App/Base.lproj/Main.storyboard create mode 100644 tools/gyp/test/ios/xctests/App/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 tools/gyp/test/ios/xctests/App/Info.plist create mode 100644 tools/gyp/test/ios/xctests/App/ViewController.h create mode 100644 tools/gyp/test/ios/xctests/App/ViewController.m create mode 100644 tools/gyp/test/ios/xctests/App/main.m create mode 100644 tools/gyp/test/ios/xctests/AppTests/AppTests.m create mode 100644 tools/gyp/test/ios/xctests/AppTests/Info.plist create mode 100644 tools/gyp/test/ios/xctests/gyptest-xctests.py create mode 100644 tools/gyp/test/ios/xctests/xctests.gyp create mode 100644 tools/gyp/test/library/gyptest-shared-obj-install-path.py create mode 100644 tools/gyp/test/library/gyptest-shared.py create mode 100644 tools/gyp/test/library/gyptest-static.py create mode 100644 tools/gyp/test/library/src/lib1.c create mode 100644 tools/gyp/test/library/src/lib1_moveable.c create mode 100644 tools/gyp/test/library/src/lib2.c create mode 100644 tools/gyp/test/library/src/lib2_moveable.c create mode 100644 tools/gyp/test/library/src/library.gyp create mode 100644 tools/gyp/test/library/src/program.c create mode 100644 tools/gyp/test/library/src/shared_dependency.gyp create mode 100644 tools/gyp/test/library_dirs/gyptest-library-dirs.py create mode 100644 tools/gyp/test/library_dirs/subdir/README.txt create mode 100644 tools/gyp/test/library_dirs/subdir/hello.cc create mode 100644 tools/gyp/test/library_dirs/subdir/mylib.cc create mode 100644 tools/gyp/test/library_dirs/subdir/mylib.h create mode 100644 tools/gyp/test/library_dirs/subdir/test-win.gyp create mode 100644 tools/gyp/test/library_dirs/subdir/test.gyp create mode 100644 tools/gyp/test/link-dependency/gyptest-link-dependency.py create mode 100644 tools/gyp/test/link-dependency/main.c create mode 100644 tools/gyp/test/link-dependency/mymalloc.c create mode 100644 tools/gyp/test/link-dependency/test.gyp create mode 100644 tools/gyp/test/link-objects/base.c create mode 100644 tools/gyp/test/link-objects/extra.c create mode 100644 tools/gyp/test/link-objects/gyptest-all.py create mode 100644 tools/gyp/test/link-objects/link-objects.gyp create mode 100644 tools/gyp/test/linux/gyptest-implicit-rpath.py create mode 100644 tools/gyp/test/linux/gyptest-ldflags-duplicates.py create mode 100644 tools/gyp/test/linux/gyptest-ldflags-from-environment.py create mode 100644 tools/gyp/test/linux/gyptest-target-rpath.py create mode 100644 tools/gyp/test/linux/implicit-rpath/file.c create mode 100644 tools/gyp/test/linux/implicit-rpath/main.c create mode 100644 tools/gyp/test/linux/implicit-rpath/test.gyp create mode 100644 tools/gyp/test/linux/ldflags-duplicates/check-ldflags.py create mode 100644 tools/gyp/test/linux/ldflags-duplicates/lib1.c create mode 100644 tools/gyp/test/linux/ldflags-duplicates/lib2.c create mode 100644 tools/gyp/test/linux/ldflags-duplicates/main.c create mode 100644 tools/gyp/test/linux/ldflags-duplicates/test.gyp create mode 100644 tools/gyp/test/linux/ldflags-from-environment/main.c create mode 100644 tools/gyp/test/linux/ldflags-from-environment/test.gyp create mode 100644 tools/gyp/test/linux/target-rpath/file.c create mode 100644 tools/gyp/test/linux/target-rpath/main.c create mode 100644 tools/gyp/test/linux/target-rpath/test.gyp create mode 100644 tools/gyp/test/mac/action-envvars/action/action.gyp create mode 100644 tools/gyp/test/mac/action-envvars/action/action.sh create mode 100644 tools/gyp/test/mac/app-bundle/TestApp/English.lproj/InfoPlist-error.strings create mode 100644 tools/gyp/test/mac/app-bundle/TestApp/English.lproj/InfoPlist.strings create mode 100644 tools/gyp/test/mac/app-bundle/TestApp/English.lproj/MainMenu.xib create mode 100644 tools/gyp/test/mac/app-bundle/TestApp/English.lproj/utf-16be.strings create mode 100644 tools/gyp/test/mac/app-bundle/TestApp/English.lproj/utf-16le.strings create mode 100644 tools/gyp/test/mac/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 tools/gyp/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json create mode 100644 tools/gyp/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png create mode 100644 tools/gyp/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png create mode 100644 tools/gyp/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png create mode 100644 tools/gyp/test/mac/app-bundle/TestApp/TestApp-Info.plist create mode 100644 tools/gyp/test/mac/app-bundle/TestApp/TestAppAppDelegate.h create mode 100644 tools/gyp/test/mac/app-bundle/TestApp/TestAppAppDelegate.m create mode 100644 tools/gyp/test/mac/app-bundle/TestApp/main.m create mode 100644 tools/gyp/test/mac/app-bundle/empty.c create mode 100644 tools/gyp/test/mac/app-bundle/test-assets-catalog.gyp create mode 100644 tools/gyp/test/mac/app-bundle/test-error.gyp create mode 100644 tools/gyp/test/mac/app-bundle/test.gyp create mode 100644 tools/gyp/test/mac/archs/empty_main.cc create mode 100644 tools/gyp/test/mac/archs/file.mm create mode 100644 tools/gyp/test/mac/archs/file_a.cc create mode 100644 tools/gyp/test/mac/archs/file_a.h create mode 100644 tools/gyp/test/mac/archs/file_b.cc create mode 100644 tools/gyp/test/mac/archs/file_b.h create mode 100644 tools/gyp/test/mac/archs/file_c.cc create mode 100644 tools/gyp/test/mac/archs/file_d.cc create mode 100644 tools/gyp/test/mac/archs/header.h create mode 100644 tools/gyp/test/mac/archs/my_file.cc create mode 100644 tools/gyp/test/mac/archs/my_main_file.cc create mode 100644 tools/gyp/test/mac/archs/test-archs-multiarch.gyp create mode 100644 tools/gyp/test/mac/archs/test-archs-x86_64.gyp create mode 100644 tools/gyp/test/mac/archs/test-dependencies.gyp create mode 100644 tools/gyp/test/mac/archs/test-no-archs.gyp create mode 100644 tools/gyp/test/mac/archs/test-valid-archs.gyp create mode 100644 tools/gyp/test/mac/bundle-resources/change.sh create mode 100644 tools/gyp/test/mac/bundle-resources/executable-file.sh create mode 100644 tools/gyp/test/mac/bundle-resources/secret.txt create mode 100644 tools/gyp/test/mac/bundle-resources/test.gyp create mode 100644 tools/gyp/test/mac/cflags/ccfile.cc create mode 100644 tools/gyp/test/mac/cflags/ccfile_withcflags.cc create mode 100644 tools/gyp/test/mac/cflags/cfile.c create mode 100644 tools/gyp/test/mac/cflags/cppfile.cpp create mode 100644 tools/gyp/test/mac/cflags/cppfile_withcflags.cpp create mode 100644 tools/gyp/test/mac/cflags/cxxfile.cxx create mode 100644 tools/gyp/test/mac/cflags/cxxfile_withcflags.cxx create mode 100644 tools/gyp/test/mac/cflags/mfile.m create mode 100644 tools/gyp/test/mac/cflags/mmfile.mm create mode 100644 tools/gyp/test/mac/cflags/mmfile_withcflags.mm create mode 100644 tools/gyp/test/mac/cflags/test.gyp create mode 100644 tools/gyp/test/mac/clang-cxx-language-standard/c++11.cc create mode 100644 tools/gyp/test/mac/clang-cxx-language-standard/c++98.cc create mode 100644 tools/gyp/test/mac/clang-cxx-language-standard/clang-cxx-language-standard.gyp create mode 100644 tools/gyp/test/mac/clang-cxx-library/clang-cxx-library.gyp create mode 100644 tools/gyp/test/mac/clang-cxx-library/libc++.cc create mode 100644 tools/gyp/test/mac/clang-cxx-library/libstdc++.cc create mode 100644 tools/gyp/test/mac/copies-with-xcode-envvars/copies-with-xcode-envvars.gyp create mode 100644 tools/gyp/test/mac/copies-with-xcode-envvars/empty.c create mode 100644 tools/gyp/test/mac/copies-with-xcode-envvars/file0 create mode 100644 tools/gyp/test/mac/copies-with-xcode-envvars/file1 create mode 100644 tools/gyp/test/mac/copies-with-xcode-envvars/file10 create mode 100644 tools/gyp/test/mac/copies-with-xcode-envvars/file11 create mode 100644 tools/gyp/test/mac/copies-with-xcode-envvars/file2 create mode 100644 tools/gyp/test/mac/copies-with-xcode-envvars/file3 create mode 100644 tools/gyp/test/mac/copies-with-xcode-envvars/file4 create mode 100644 tools/gyp/test/mac/copies-with-xcode-envvars/file5 create mode 100644 tools/gyp/test/mac/copies-with-xcode-envvars/file6 create mode 100644 tools/gyp/test/mac/copies-with-xcode-envvars/file7 create mode 100644 tools/gyp/test/mac/copies-with-xcode-envvars/file8 create mode 100644 tools/gyp/test/mac/copies-with-xcode-envvars/file9 create mode 100644 tools/gyp/test/mac/copy-dylib/empty.c create mode 100644 tools/gyp/test/mac/copy-dylib/test.gyp create mode 100644 tools/gyp/test/mac/debuginfo/file.c create mode 100644 tools/gyp/test/mac/debuginfo/test.gyp create mode 100644 tools/gyp/test/mac/depend-on-bundle/English.lproj/InfoPlist.strings create mode 100644 tools/gyp/test/mac/depend-on-bundle/Info.plist create mode 100644 tools/gyp/test/mac/depend-on-bundle/bundle.c create mode 100644 tools/gyp/test/mac/depend-on-bundle/executable.c create mode 100644 tools/gyp/test/mac/depend-on-bundle/test.gyp create mode 100644 tools/gyp/test/mac/deployment-target/check-version-min.c create mode 100644 tools/gyp/test/mac/deployment-target/deployment-target.gyp create mode 100644 tools/gyp/test/mac/framework-dirs/calculate.c create mode 100644 tools/gyp/test/mac/framework-dirs/framework-dirs.gyp create mode 100644 tools/gyp/test/mac/framework-headers/myframework.h create mode 100644 tools/gyp/test/mac/framework-headers/myframework.m create mode 100644 tools/gyp/test/mac/framework-headers/test.gyp create mode 100644 tools/gyp/test/mac/framework/TestFramework/English.lproj/InfoPlist.strings create mode 100644 tools/gyp/test/mac/framework/TestFramework/Info.plist create mode 100644 tools/gyp/test/mac/framework/TestFramework/ObjCVector.h create mode 100644 tools/gyp/test/mac/framework/TestFramework/ObjCVector.mm create mode 100644 tools/gyp/test/mac/framework/TestFramework/ObjCVectorInternal.h create mode 100644 tools/gyp/test/mac/framework/TestFramework/TestFramework_Prefix.pch create mode 100644 tools/gyp/test/mac/framework/empty.c create mode 100644 tools/gyp/test/mac/framework/framework.gyp create mode 100644 tools/gyp/test/mac/global-settings/src/dir1/dir1.gyp create mode 100644 tools/gyp/test/mac/global-settings/src/dir2/dir2.gyp create mode 100644 tools/gyp/test/mac/global-settings/src/dir2/file.txt create mode 100644 tools/gyp/test/mac/gyptest-action-envvars.py create mode 100644 tools/gyp/test/mac/gyptest-app-assets-catalog.py create mode 100644 tools/gyp/test/mac/gyptest-app-error.py create mode 100644 tools/gyp/test/mac/gyptest-app.py create mode 100644 tools/gyp/test/mac/gyptest-archs.py create mode 100644 tools/gyp/test/mac/gyptest-bundle-resources.py create mode 100644 tools/gyp/test/mac/gyptest-cflags.py create mode 100644 tools/gyp/test/mac/gyptest-clang-cxx-language-standard.py create mode 100644 tools/gyp/test/mac/gyptest-clang-cxx-library.py create mode 100644 tools/gyp/test/mac/gyptest-copies-with-xcode-envvars.py create mode 100644 tools/gyp/test/mac/gyptest-copies.py create mode 100644 tools/gyp/test/mac/gyptest-copy-dylib.py create mode 100644 tools/gyp/test/mac/gyptest-debuginfo.py create mode 100644 tools/gyp/test/mac/gyptest-depend-on-bundle.py create mode 100644 tools/gyp/test/mac/gyptest-deployment-target.py create mode 100644 tools/gyp/test/mac/gyptest-framework-dirs.py create mode 100644 tools/gyp/test/mac/gyptest-framework-headers.py create mode 100644 tools/gyp/test/mac/gyptest-framework.py create mode 100644 tools/gyp/test/mac/gyptest-global-settings.py create mode 100644 tools/gyp/test/mac/gyptest-identical-name.py create mode 100644 tools/gyp/test/mac/gyptest-infoplist-process.py create mode 100644 tools/gyp/test/mac/gyptest-installname.py create mode 100644 tools/gyp/test/mac/gyptest-kext.py create mode 100644 tools/gyp/test/mac/gyptest-ldflags-passed-to-libtool.py create mode 100644 tools/gyp/test/mac/gyptest-ldflags.py create mode 100644 tools/gyp/test/mac/gyptest-libraries.py create mode 100644 tools/gyp/test/mac/gyptest-libtool-zero.py create mode 100644 tools/gyp/test/mac/gyptest-loadable-module-bundle-product-extension.py create mode 100644 tools/gyp/test/mac/gyptest-loadable-module.py create mode 100644 tools/gyp/test/mac/gyptest-lto.py create mode 100644 tools/gyp/test/mac/gyptest-missing-cfbundlesignature.py create mode 100644 tools/gyp/test/mac/gyptest-non-strs-flattened-to-env.py create mode 100644 tools/gyp/test/mac/gyptest-objc-arc.py create mode 100644 tools/gyp/test/mac/gyptest-objc-gc.py create mode 100644 tools/gyp/test/mac/gyptest-postbuild-copy-bundle.py create mode 100644 tools/gyp/test/mac/gyptest-postbuild-defaults.py create mode 100644 tools/gyp/test/mac/gyptest-postbuild-fail.py create mode 100644 tools/gyp/test/mac/gyptest-postbuild-multiple-configurations.py create mode 100644 tools/gyp/test/mac/gyptest-postbuild-static-library.py create mode 100644 tools/gyp/test/mac/gyptest-postbuild.py create mode 100644 tools/gyp/test/mac/gyptest-prefixheader.py create mode 100644 tools/gyp/test/mac/gyptest-rebuild.py create mode 100644 tools/gyp/test/mac/gyptest-rpath.py create mode 100644 tools/gyp/test/mac/gyptest-sdkroot.py create mode 100644 tools/gyp/test/mac/gyptest-sourceless-module.py create mode 100644 tools/gyp/test/mac/gyptest-strip-default.py create mode 100644 tools/gyp/test/mac/gyptest-strip.py create mode 100644 tools/gyp/test/mac/gyptest-swift-library.py create mode 100644 tools/gyp/test/mac/gyptest-type-envvars.py create mode 100644 tools/gyp/test/mac/gyptest-unicode-settings.py create mode 100644 tools/gyp/test/mac/gyptest-xcode-env-order.py create mode 100644 tools/gyp/test/mac/gyptest-xcode-gcc-clang.py create mode 100644 tools/gyp/test/mac/gyptest-xcode-gcc.py create mode 100644 tools/gyp/test/mac/gyptest-xcode-support-actions.py create mode 100644 tools/gyp/test/mac/gyptest-xctest.py create mode 100644 tools/gyp/test/mac/gyptest-xcuitest.py create mode 100644 tools/gyp/test/mac/identical-name/proxy/proxy.cc create mode 100644 tools/gyp/test/mac/identical-name/proxy/proxy.gyp create mode 100644 tools/gyp/test/mac/identical-name/proxy/testlib/testlib.cc create mode 100644 tools/gyp/test/mac/identical-name/proxy/testlib/testlib.gyp create mode 100644 tools/gyp/test/mac/identical-name/test-should-fail.gyp create mode 100644 tools/gyp/test/mac/identical-name/test.gyp create mode 100644 tools/gyp/test/mac/identical-name/test.gypi create mode 100644 tools/gyp/test/mac/identical-name/testlib/main.cc create mode 100644 tools/gyp/test/mac/identical-name/testlib/testlib.gyp create mode 100644 tools/gyp/test/mac/identical-name/testlib/void.cc create mode 100644 tools/gyp/test/mac/infoplist-process/Info.plist create mode 100644 tools/gyp/test/mac/infoplist-process/main.c create mode 100644 tools/gyp/test/mac/infoplist-process/test1.gyp create mode 100644 tools/gyp/test/mac/infoplist-process/test2.gyp create mode 100644 tools/gyp/test/mac/infoplist-process/test3.gyp create mode 100644 tools/gyp/test/mac/installname/Info.plist create mode 100644 tools/gyp/test/mac/installname/file.c create mode 100644 tools/gyp/test/mac/installname/main.c create mode 100644 tools/gyp/test/mac/installname/test.gyp create mode 100644 tools/gyp/test/mac/kext/GypKext/GypKext-Info.plist create mode 100644 tools/gyp/test/mac/kext/GypKext/GypKext.c create mode 100644 tools/gyp/test/mac/kext/kext.gyp create mode 100644 tools/gyp/test/mac/ldflags-libtool/file.c create mode 100644 tools/gyp/test/mac/ldflags-libtool/test.gyp create mode 100644 tools/gyp/test/mac/ldflags/subdirectory/Info.plist create mode 100644 tools/gyp/test/mac/ldflags/subdirectory/file.c create mode 100644 tools/gyp/test/mac/ldflags/subdirectory/symbol_list.def create mode 100644 tools/gyp/test/mac/ldflags/subdirectory/test.gyp create mode 100644 tools/gyp/test/mac/libraries/subdir/README.txt create mode 100644 tools/gyp/test/mac/libraries/subdir/hello.cc create mode 100644 tools/gyp/test/mac/libraries/subdir/mylib.c create mode 100644 tools/gyp/test/mac/libraries/subdir/test.gyp create mode 100644 tools/gyp/test/mac/libtool-zero/mylib.c create mode 100644 tools/gyp/test/mac/libtool-zero/test.gyp create mode 100644 tools/gyp/test/mac/loadable-module-bundle-product-extension/src.cc create mode 100644 tools/gyp/test/mac/loadable-module-bundle-product-extension/test.gyp create mode 100644 tools/gyp/test/mac/loadable-module/Info.plist create mode 100644 tools/gyp/test/mac/loadable-module/module.c create mode 100644 tools/gyp/test/mac/loadable-module/test.gyp create mode 100644 tools/gyp/test/mac/lto/asmfile.S create mode 100644 tools/gyp/test/mac/lto/ccfile.cc create mode 100644 tools/gyp/test/mac/lto/cfile.c create mode 100644 tools/gyp/test/mac/lto/mfile.m create mode 100644 tools/gyp/test/mac/lto/mmfile.mm create mode 100644 tools/gyp/test/mac/lto/test.gyp create mode 100644 tools/gyp/test/mac/missing-cfbundlesignature/Info.plist create mode 100644 tools/gyp/test/mac/missing-cfbundlesignature/Other-Info.plist create mode 100644 tools/gyp/test/mac/missing-cfbundlesignature/Third-Info.plist create mode 100644 tools/gyp/test/mac/missing-cfbundlesignature/file.c create mode 100644 tools/gyp/test/mac/missing-cfbundlesignature/test.gyp create mode 100644 tools/gyp/test/mac/non-strs-flattened-to-env/Info.plist create mode 100644 tools/gyp/test/mac/non-strs-flattened-to-env/main.c create mode 100644 tools/gyp/test/mac/non-strs-flattened-to-env/test.gyp create mode 100644 tools/gyp/test/mac/objc-arc/c-file.c create mode 100644 tools/gyp/test/mac/objc-arc/cc-file.cc create mode 100644 tools/gyp/test/mac/objc-arc/m-file-no-arc.m create mode 100644 tools/gyp/test/mac/objc-arc/m-file.m create mode 100644 tools/gyp/test/mac/objc-arc/mm-file-no-arc.mm create mode 100644 tools/gyp/test/mac/objc-arc/mm-file.mm create mode 100644 tools/gyp/test/mac/objc-arc/test.gyp create mode 100644 tools/gyp/test/mac/objc-gc/c-file.c create mode 100644 tools/gyp/test/mac/objc-gc/cc-file.cc create mode 100644 tools/gyp/test/mac/objc-gc/main.m create mode 100644 tools/gyp/test/mac/objc-gc/needs-gc-mm.mm create mode 100644 tools/gyp/test/mac/objc-gc/needs-gc.m create mode 100644 tools/gyp/test/mac/objc-gc/test.gyp create mode 100644 tools/gyp/test/mac/postbuild-copy-bundle/Framework-Info.plist create mode 100644 tools/gyp/test/mac/postbuild-copy-bundle/TestApp-Info.plist create mode 100644 tools/gyp/test/mac/postbuild-copy-bundle/copied.txt create mode 100644 tools/gyp/test/mac/postbuild-copy-bundle/empty.c create mode 100644 tools/gyp/test/mac/postbuild-copy-bundle/main.c create mode 100644 tools/gyp/test/mac/postbuild-copy-bundle/postbuild-copy-framework.sh create mode 100644 tools/gyp/test/mac/postbuild-copy-bundle/resource_file.sb create mode 100644 tools/gyp/test/mac/postbuild-copy-bundle/test.gyp create mode 100644 tools/gyp/test/mac/postbuild-defaults/Info.plist create mode 100644 tools/gyp/test/mac/postbuild-defaults/main.c create mode 100644 tools/gyp/test/mac/postbuild-defaults/postbuild-defaults.sh create mode 100644 tools/gyp/test/mac/postbuild-defaults/test.gyp create mode 100644 tools/gyp/test/mac/postbuild-fail/file.c create mode 100644 tools/gyp/test/mac/postbuild-fail/postbuild-fail.sh create mode 100644 tools/gyp/test/mac/postbuild-fail/test.gyp create mode 100644 tools/gyp/test/mac/postbuild-fail/touch-dynamic.sh create mode 100644 tools/gyp/test/mac/postbuild-fail/touch-static.sh create mode 100644 tools/gyp/test/mac/postbuild-multiple-configurations/main.c create mode 100644 tools/gyp/test/mac/postbuild-multiple-configurations/postbuild-touch-file.sh create mode 100644 tools/gyp/test/mac/postbuild-multiple-configurations/test.gyp create mode 100644 tools/gyp/test/mac/postbuild-static-library/empty.c create mode 100644 tools/gyp/test/mac/postbuild-static-library/postbuild-touch-file.sh create mode 100644 tools/gyp/test/mac/postbuild-static-library/test.gyp create mode 100644 tools/gyp/test/mac/postbuilds/copy.sh create mode 100644 tools/gyp/test/mac/postbuilds/file.c create mode 100644 tools/gyp/test/mac/postbuilds/file_g.c create mode 100644 tools/gyp/test/mac/postbuilds/file_h.c create mode 100644 tools/gyp/test/mac/postbuilds/script/shared_library_postbuild.sh create mode 100644 tools/gyp/test/mac/postbuilds/script/static_library_postbuild.sh create mode 100644 tools/gyp/test/mac/postbuilds/subdirectory/copied_file.txt create mode 100644 tools/gyp/test/mac/postbuilds/subdirectory/nested_target.gyp create mode 100644 tools/gyp/test/mac/postbuilds/test.gyp create mode 100644 tools/gyp/test/mac/prefixheader/file.c create mode 100644 tools/gyp/test/mac/prefixheader/file.cc create mode 100644 tools/gyp/test/mac/prefixheader/file.m create mode 100644 tools/gyp/test/mac/prefixheader/file.mm create mode 100644 tools/gyp/test/mac/prefixheader/header.h create mode 100644 tools/gyp/test/mac/prefixheader/test.gyp create mode 100644 tools/gyp/test/mac/rebuild/TestApp-Info.plist create mode 100644 tools/gyp/test/mac/rebuild/delay-touch.sh create mode 100644 tools/gyp/test/mac/rebuild/empty.c create mode 100644 tools/gyp/test/mac/rebuild/main.c create mode 100644 tools/gyp/test/mac/rebuild/test.gyp create mode 100644 tools/gyp/test/mac/rpath/file.c create mode 100644 tools/gyp/test/mac/rpath/main.c create mode 100644 tools/gyp/test/mac/rpath/test.gyp create mode 100644 tools/gyp/test/mac/sdkroot/file.cc create mode 100644 tools/gyp/test/mac/sdkroot/test.gyp create mode 100644 tools/gyp/test/mac/sdkroot/test_shorthand.sh create mode 100644 tools/gyp/test/mac/sourceless-module/empty.c create mode 100644 tools/gyp/test/mac/sourceless-module/empty.txt create mode 100644 tools/gyp/test/mac/sourceless-module/fun.c create mode 100644 tools/gyp/test/mac/sourceless-module/test.gyp create mode 100644 tools/gyp/test/mac/strip/file.c create mode 100644 tools/gyp/test/mac/strip/main.c create mode 100644 tools/gyp/test/mac/strip/strip.saves create mode 100644 tools/gyp/test/mac/strip/subdirectory/nested_file.c create mode 100644 tools/gyp/test/mac/strip/subdirectory/nested_strip.saves create mode 100644 tools/gyp/test/mac/strip/subdirectory/subdirectory.gyp create mode 100644 tools/gyp/test/mac/strip/subdirectory/test_reading_save_file_from_postbuild.sh create mode 100644 tools/gyp/test/mac/strip/test-defaults.gyp create mode 100644 tools/gyp/test/mac/strip/test.gyp create mode 100644 tools/gyp/test/mac/swift-library/Info.plist create mode 100644 tools/gyp/test/mac/swift-library/file.swift create mode 100644 tools/gyp/test/mac/swift-library/test.gyp create mode 100644 tools/gyp/test/mac/type_envvars/file.c create mode 100644 tools/gyp/test/mac/type_envvars/test.gyp create mode 100644 tools/gyp/test/mac/type_envvars/test_bundle_executable.sh create mode 100644 tools/gyp/test/mac/type_envvars/test_bundle_loadable_module.sh create mode 100644 tools/gyp/test/mac/type_envvars/test_bundle_shared_library.sh create mode 100644 tools/gyp/test/mac/type_envvars/test_check_sdkroot.sh create mode 100644 tools/gyp/test/mac/type_envvars/test_nonbundle_executable.sh create mode 100644 tools/gyp/test/mac/type_envvars/test_nonbundle_loadable_module.sh create mode 100644 tools/gyp/test/mac/type_envvars/test_nonbundle_none.sh create mode 100644 tools/gyp/test/mac/type_envvars/test_nonbundle_shared_library.sh create mode 100644 tools/gyp/test/mac/type_envvars/test_nonbundle_static_library.sh create mode 100644 tools/gyp/test/mac/unicode-settings/file.cc create mode 100644 tools/gyp/test/mac/unicode-settings/test.gyp create mode 100644 tools/gyp/test/mac/unicode-settings/test_bundle_display_name.sh create mode 100644 tools/gyp/test/mac/xcode-env-order/Info.plist create mode 100644 tools/gyp/test/mac/xcode-env-order/file.ext1 create mode 100644 tools/gyp/test/mac/xcode-env-order/file.ext2 create mode 100644 tools/gyp/test/mac/xcode-env-order/file.ext3 create mode 100644 tools/gyp/test/mac/xcode-env-order/main.c create mode 100644 tools/gyp/test/mac/xcode-env-order/test.gyp create mode 100644 tools/gyp/test/mac/xcode-gcc/aliasing.cc create mode 100644 tools/gyp/test/mac/xcode-gcc/test-clang.gyp create mode 100644 tools/gyp/test/mac/xcode-gcc/test.gyp create mode 100644 tools/gyp/test/mac/xcode-gcc/valid_c.c create mode 100644 tools/gyp/test/mac/xcode-gcc/valid_cc.cc create mode 100644 tools/gyp/test/mac/xcode-gcc/valid_m.m create mode 100644 tools/gyp/test/mac/xcode-gcc/valid_mm.mm create mode 100644 tools/gyp/test/mac/xcode-gcc/warn_about_invalid_offsetof_macro.cc create mode 100644 tools/gyp/test/mac/xcode-gcc/warn_about_missing_newline.c create mode 100644 tools/gyp/test/mac/xcode-support-actions/source.c create mode 100644 tools/gyp/test/mac/xcode-support-actions/test.gyp create mode 100644 tools/gyp/test/mac/xctest/MyClass.h create mode 100644 tools/gyp/test/mac/xctest/MyClass.m create mode 100644 tools/gyp/test/mac/xctest/TestCase.m create mode 100644 tools/gyp/test/mac/xctest/resource.txt create mode 100644 tools/gyp/test/mac/xctest/test.gyp create mode 100644 tools/gyp/test/mac/xcuitest/Info.plist create mode 100644 tools/gyp/test/mac/xcuitest/MyAppDelegate.h create mode 100644 tools/gyp/test/mac/xcuitest/MyAppDelegate.m create mode 100644 tools/gyp/test/mac/xcuitest/TestCase.m create mode 100644 tools/gyp/test/mac/xcuitest/main.m create mode 100644 tools/gyp/test/mac/xcuitest/resource.txt create mode 100644 tools/gyp/test/mac/xcuitest/test.gyp create mode 100644 tools/gyp/test/make/dependencies.gyp create mode 100644 tools/gyp/test/make/gyptest-dependencies.py create mode 100644 tools/gyp/test/make/gyptest-noload.py create mode 100644 tools/gyp/test/make/main.cc create mode 100644 tools/gyp/test/make/main.h create mode 100644 tools/gyp/test/make/noload/all.gyp create mode 100644 tools/gyp/test/make/noload/lib/shared.c create mode 100644 tools/gyp/test/make/noload/lib/shared.gyp create mode 100644 tools/gyp/test/make/noload/lib/shared.h create mode 100644 tools/gyp/test/make/noload/main.c create mode 100644 tools/gyp/test/make_global_settings/ar/gyptest-make_global_settings_ar.py create mode 100644 tools/gyp/test/make_global_settings/ar/make_global_settings_ar.gyp create mode 100644 tools/gyp/test/make_global_settings/basics/gyptest-make_global_settings.py create mode 100644 tools/gyp/test/make_global_settings/basics/make_global_settings.gyp create mode 100644 tools/gyp/test/make_global_settings/env-wrapper/gyptest-wrapper.py create mode 100644 tools/gyp/test/make_global_settings/env-wrapper/wrapper.gyp create mode 100644 tools/gyp/test/make_global_settings/full-toolchain/bar.cc create mode 100644 tools/gyp/test/make_global_settings/full-toolchain/foo.c create mode 100644 tools/gyp/test/make_global_settings/full-toolchain/gyptest-make_global_settings.py create mode 100644 tools/gyp/test/make_global_settings/full-toolchain/make_global_settings.gyp create mode 100644 tools/gyp/test/make_global_settings/full-toolchain/my_nm.py create mode 100644 tools/gyp/test/make_global_settings/full-toolchain/my_readelf.py create mode 100644 tools/gyp/test/make_global_settings/ld/gyptest-make_global_settings_ld.py create mode 100644 tools/gyp/test/make_global_settings/ld/make_global_settings_ld.gyp create mode 100644 tools/gyp/test/make_global_settings/wrapper/gyptest-wrapper.py create mode 100644 tools/gyp/test/make_global_settings/wrapper/wrapper.gyp create mode 100644 tools/gyp/test/many-actions/file0 create mode 100644 tools/gyp/test/many-actions/file1 create mode 100644 tools/gyp/test/many-actions/file2 create mode 100644 tools/gyp/test/many-actions/file3 create mode 100644 tools/gyp/test/many-actions/file4 create mode 100644 tools/gyp/test/many-actions/gyptest-many-actions-unsorted.py create mode 100644 tools/gyp/test/many-actions/gyptest-many-actions.py create mode 100644 tools/gyp/test/many-actions/many-actions-unsorted.gyp create mode 100644 tools/gyp/test/many-actions/many-actions.gyp create mode 100644 tools/gyp/test/module/gyptest-default.py create mode 100644 tools/gyp/test/module/src/lib1.c create mode 100644 tools/gyp/test/module/src/lib2.c create mode 100644 tools/gyp/test/module/src/module.gyp create mode 100644 tools/gyp/test/module/src/program.c create mode 100644 tools/gyp/test/msvs/buildevents/buildevents.gyp create mode 100644 tools/gyp/test/msvs/buildevents/gyptest-msbuild-supports-prepostbuild.py create mode 100644 tools/gyp/test/msvs/buildevents/gyptest-ninja-warnings.py create mode 100644 tools/gyp/test/msvs/buildevents/main.cc create mode 100644 tools/gyp/test/msvs/config_attrs/gyptest-config_attrs.py create mode 100644 tools/gyp/test/msvs/config_attrs/hello.c create mode 100644 tools/gyp/test/msvs/config_attrs/hello.gyp create mode 100644 tools/gyp/test/msvs/express/base/base.gyp create mode 100644 tools/gyp/test/msvs/express/express.gyp create mode 100644 tools/gyp/test/msvs/express/gyptest-express.py create mode 100644 tools/gyp/test/msvs/external_builder/external.gyp create mode 100644 tools/gyp/test/msvs/external_builder/external_builder.py create mode 100644 tools/gyp/test/msvs/external_builder/gyptest-all.py create mode 100644 tools/gyp/test/msvs/external_builder/hello.cpp create mode 100644 tools/gyp/test/msvs/external_builder/hello.z create mode 100644 tools/gyp/test/msvs/external_builder/msbuild_action.py create mode 100644 tools/gyp/test/msvs/external_builder/msbuild_rule.py create mode 100644 tools/gyp/test/msvs/filters/filters.gyp create mode 100644 tools/gyp/test/msvs/filters/gyptest-filters-2008.py create mode 100644 tools/gyp/test/msvs/filters/gyptest-filters-2010.py create mode 100644 tools/gyp/test/msvs/list_excluded/gyptest-all.py create mode 100644 tools/gyp/test/msvs/list_excluded/hello.cpp create mode 100644 tools/gyp/test/msvs/list_excluded/hello_exclude.gyp create mode 100644 tools/gyp/test/msvs/list_excluded/hello_mac.cpp create mode 100644 tools/gyp/test/msvs/missing_sources/gyptest-missing.py create mode 100644 tools/gyp/test/msvs/missing_sources/hello_missing.gyp create mode 100644 tools/gyp/test/msvs/multiple_actions_error_handling/action_fail.py create mode 100644 tools/gyp/test/msvs/multiple_actions_error_handling/action_succeed.py create mode 100644 tools/gyp/test/msvs/multiple_actions_error_handling/actions.gyp create mode 100644 tools/gyp/test/msvs/multiple_actions_error_handling/gyptest.py create mode 100644 tools/gyp/test/msvs/props/AppName.props create mode 100644 tools/gyp/test/msvs/props/AppName.vsprops create mode 100644 tools/gyp/test/msvs/props/gyptest-props.py create mode 100644 tools/gyp/test/msvs/props/hello.c create mode 100644 tools/gyp/test/msvs/props/hello.gyp create mode 100644 tools/gyp/test/msvs/rules_stdout_stderr/dummy.bar create mode 100644 tools/gyp/test/msvs/rules_stdout_stderr/dummy.foo create mode 100644 tools/gyp/test/msvs/rules_stdout_stderr/gyptest-rules-stdout-stderr.py create mode 100644 tools/gyp/test/msvs/rules_stdout_stderr/rule_stderr.py create mode 100644 tools/gyp/test/msvs/rules_stdout_stderr/rule_stdout.py create mode 100644 tools/gyp/test/msvs/rules_stdout_stderr/rules-stdout-stderr.gyp create mode 100644 tools/gyp/test/msvs/shared_output/common.gypi create mode 100644 tools/gyp/test/msvs/shared_output/gyptest-shared_output.py create mode 100644 tools/gyp/test/msvs/shared_output/hello.c create mode 100644 tools/gyp/test/msvs/shared_output/hello.gyp create mode 100644 tools/gyp/test/msvs/shared_output/there/there.c create mode 100644 tools/gyp/test/msvs/shared_output/there/there.gyp create mode 100644 tools/gyp/test/msvs/uldi2010/gyptest-all.py create mode 100644 tools/gyp/test/msvs/uldi2010/hello.c create mode 100644 tools/gyp/test/msvs/uldi2010/hello.gyp create mode 100644 tools/gyp/test/msvs/uldi2010/hello2.c create mode 100644 tools/gyp/test/multiple-targets/gyptest-all.py create mode 100644 tools/gyp/test/multiple-targets/gyptest-default.py create mode 100644 tools/gyp/test/multiple-targets/src/common.c create mode 100644 tools/gyp/test/multiple-targets/src/multiple.gyp create mode 100644 tools/gyp/test/multiple-targets/src/prog1.c create mode 100644 tools/gyp/test/multiple-targets/src/prog2.c create mode 100644 tools/gyp/test/ninja/action-rule-hash/gyptest-action-rule-hash.py create mode 100644 tools/gyp/test/ninja/action-rule-hash/subdir/action-rule-hash.gyp create mode 100644 tools/gyp/test/ninja/action-rule-hash/subdir/emit.py create mode 100644 tools/gyp/test/ninja/action_dependencies/gyptest-action-dependencies.py create mode 100644 tools/gyp/test/ninja/action_dependencies/src/a.c create mode 100644 tools/gyp/test/ninja/action_dependencies/src/a.h create mode 100644 tools/gyp/test/ninja/action_dependencies/src/action_dependencies.gyp create mode 100644 tools/gyp/test/ninja/action_dependencies/src/b.c create mode 100644 tools/gyp/test/ninja/action_dependencies/src/b.h create mode 100644 tools/gyp/test/ninja/action_dependencies/src/c.c create mode 100644 tools/gyp/test/ninja/action_dependencies/src/c.h create mode 100644 tools/gyp/test/ninja/action_dependencies/src/emit.py create mode 100644 tools/gyp/test/ninja/chained-dependency/chained-dependency.gyp create mode 100644 tools/gyp/test/ninja/chained-dependency/chained.c create mode 100644 tools/gyp/test/ninja/chained-dependency/gyptest-chained-dependency.py create mode 100644 tools/gyp/test/ninja/empty-and-non-empty-duplicate-name/gyptest-empty-and-non-empty-duplicate-name.py create mode 100644 tools/gyp/test/ninja/empty-and-non-empty-duplicate-name/subdir/included.gyp create mode 100644 tools/gyp/test/ninja/empty-and-non-empty-duplicate-name/test.gyp create mode 100644 tools/gyp/test/ninja/normalize-paths-win/gyptest-normalize-paths.py create mode 100644 tools/gyp/test/ninja/normalize-paths-win/hello.cc create mode 100644 tools/gyp/test/ninja/normalize-paths-win/normalize-paths.gyp create mode 100644 tools/gyp/test/ninja/s-needs-no-depfiles/empty.s create mode 100644 tools/gyp/test/ninja/s-needs-no-depfiles/gyptest-s-needs-no-depfiles.py create mode 100644 tools/gyp/test/ninja/s-needs-no-depfiles/s-needs-no-depfiles.gyp create mode 100644 tools/gyp/test/ninja/solibs_avoid_relinking/gyptest-solibs-avoid-relinking.py create mode 100644 tools/gyp/test/ninja/solibs_avoid_relinking/main.cc create mode 100644 tools/gyp/test/ninja/solibs_avoid_relinking/solib.cc create mode 100644 tools/gyp/test/ninja/solibs_avoid_relinking/solibs_avoid_relinking.gyp create mode 100644 tools/gyp/test/ninja/use-console/foo.bar create mode 100644 tools/gyp/test/ninja/use-console/gyptest-use-console.py create mode 100644 tools/gyp/test/ninja/use-console/use-console.gyp create mode 100644 tools/gyp/test/ninja/use-custom-environment-files/gyptest-use-custom-environment-files.py create mode 100644 tools/gyp/test/ninja/use-custom-environment-files/use-custom-environment-files.cc create mode 100644 tools/gyp/test/ninja/use-custom-environment-files/use-custom-environment-files.gyp create mode 100644 tools/gyp/test/no-cpp/gyptest-no-cpp.py create mode 100644 tools/gyp/test/no-cpp/src/call-f-main.c create mode 100644 tools/gyp/test/no-cpp/src/empty-main.c create mode 100644 tools/gyp/test/no-cpp/src/f.cc create mode 100644 tools/gyp/test/no-cpp/src/test.gyp create mode 100644 tools/gyp/test/no-output/gyptest-no-output.py create mode 100644 tools/gyp/test/no-output/src/nooutput.gyp create mode 100644 tools/gyp/test/product/gyptest-product.py create mode 100644 tools/gyp/test/product/hello.c create mode 100644 tools/gyp/test/product/product.gyp create mode 100644 tools/gyp/test/prune_targets/gyptest-prune-targets.py create mode 100644 tools/gyp/test/prune_targets/lib1.cc create mode 100644 tools/gyp/test/prune_targets/lib2.cc create mode 100644 tools/gyp/test/prune_targets/lib3.cc create mode 100644 tools/gyp/test/prune_targets/lib_indirect.cc create mode 100644 tools/gyp/test/prune_targets/program.cc create mode 100644 tools/gyp/test/prune_targets/test1.gyp create mode 100644 tools/gyp/test/prune_targets/test2.gyp create mode 100644 tools/gyp/test/relative/foo/a/a.cc create mode 100644 tools/gyp/test/relative/foo/a/a.gyp create mode 100644 tools/gyp/test/relative/foo/a/c/c.cc create mode 100644 tools/gyp/test/relative/foo/a/c/c.gyp create mode 100644 tools/gyp/test/relative/foo/b/b.cc create mode 100644 tools/gyp/test/relative/foo/b/b.gyp create mode 100644 tools/gyp/test/relative/gyptest-default.py create mode 100644 tools/gyp/test/rename/filecase/file.c create mode 100644 tools/gyp/test/rename/filecase/test-casesensitive.gyp create mode 100644 tools/gyp/test/rename/filecase/test.gyp create mode 100644 tools/gyp/test/rename/gyptest-filecase.py create mode 100644 tools/gyp/test/restat/gyptest-restat.py create mode 100644 tools/gyp/test/restat/src/create_intermediate.py create mode 100644 tools/gyp/test/restat/src/restat.gyp create mode 100644 tools/gyp/test/restat/src/touch.py create mode 100644 tools/gyp/test/rules/dirname/gyptest-dirname.py create mode 100644 tools/gyp/test/rules/dirname/src/actions.gyp create mode 100644 tools/gyp/test/rules/dirname/src/copy-file.py create mode 100644 tools/gyp/test/rules/dirname/src/subdir/a/b/c.gencc create mode 100644 tools/gyp/test/rules/dirname/src/subdir/a/b/c.printvars create mode 100644 tools/gyp/test/rules/dirname/src/subdir/foo/bar/baz.gencc create mode 100644 tools/gyp/test/rules/dirname/src/subdir/foo/bar/baz.printvars create mode 100644 tools/gyp/test/rules/dirname/src/subdir/input-rule-dirname.gyp create mode 100644 tools/gyp/test/rules/dirname/src/subdir/main.cc create mode 100644 tools/gyp/test/rules/dirname/src/subdir/nodir.gencc create mode 100644 tools/gyp/test/rules/dirname/src/subdir/printvars.py create mode 100644 tools/gyp/test/rules/e2e/gyptest-all.py create mode 100644 tools/gyp/test/rules/e2e/gyptest-default.py create mode 100644 tools/gyp/test/rules/e2e/gyptest-input-root.py create mode 100644 tools/gyp/test/rules/e2e/gyptest-special-variables.py create mode 100644 tools/gyp/test/rules/e2e/src/actions.gyp create mode 100644 tools/gyp/test/rules/e2e/src/an_asm.S create mode 100644 tools/gyp/test/rules/e2e/src/as.bat create mode 100644 tools/gyp/test/rules/e2e/src/copy-file.py create mode 100644 tools/gyp/test/rules/e2e/src/external/external.gyp create mode 100644 tools/gyp/test/rules/e2e/src/external/file1.in create mode 100644 tools/gyp/test/rules/e2e/src/external/file2.in create mode 100644 tools/gyp/test/rules/e2e/src/input-root.gyp create mode 100644 tools/gyp/test/rules/e2e/src/noaction/file1.in create mode 100644 tools/gyp/test/rules/e2e/src/noaction/no_action_with_rules_fails.gyp create mode 100644 tools/gyp/test/rules/e2e/src/rule.py create mode 100644 tools/gyp/test/rules/e2e/src/somefile.ext create mode 100644 tools/gyp/test/rules/e2e/src/special-variables.gyp create mode 100644 tools/gyp/test/rules/e2e/src/subdir1/executable.gyp create mode 100644 tools/gyp/test/rules/e2e/src/subdir1/function1.in create mode 100644 tools/gyp/test/rules/e2e/src/subdir1/function2.in create mode 100644 tools/gyp/test/rules/e2e/src/subdir1/program.c create mode 100644 tools/gyp/test/rules/e2e/src/subdir2/both_rule_and_action_input.gyp create mode 100644 tools/gyp/test/rules/e2e/src/subdir2/file1.in create mode 100644 tools/gyp/test/rules/e2e/src/subdir2/file2.in create mode 100644 tools/gyp/test/rules/e2e/src/subdir2/never_used.gyp create mode 100644 tools/gyp/test/rules/e2e/src/subdir2/no_action.gyp create mode 100644 tools/gyp/test/rules/e2e/src/subdir2/no_inputs.gyp create mode 100644 tools/gyp/test/rules/e2e/src/subdir2/none.gyp create mode 100644 tools/gyp/test/rules/e2e/src/subdir2/program.c create mode 100644 tools/gyp/test/rules/e2e/src/subdir3/executable2.gyp create mode 100644 tools/gyp/test/rules/e2e/src/subdir3/function3.in create mode 100644 tools/gyp/test/rules/e2e/src/subdir3/program.c create mode 100644 tools/gyp/test/rules/e2e/src/subdir4/asm-function.assem create mode 100644 tools/gyp/test/rules/e2e/src/subdir4/build-asm.gyp create mode 100644 tools/gyp/test/rules/e2e/src/subdir4/program.c create mode 100644 tools/gyp/test/rules/rebuild/gyptest-all.py create mode 100644 tools/gyp/test/rules/rebuild/gyptest-default.py create mode 100644 tools/gyp/test/rules/rebuild/src/main.c create mode 100644 tools/gyp/test/rules/rebuild/src/make-sources.py create mode 100644 tools/gyp/test/rules/rebuild/src/prog1.in create mode 100644 tools/gyp/test/rules/rebuild/src/prog2.in create mode 100644 tools/gyp/test/rules/rebuild/src/same_target.gyp create mode 100644 tools/gyp/test/rules/use-built-dependencies/gyptest-use-built-dependencies.py create mode 100644 tools/gyp/test/rules/use-built-dependencies/src/main.cc create mode 100644 tools/gyp/test/rules/use-built-dependencies/src/use-built-dependencies-rule.gyp create mode 100644 tools/gyp/test/rules/variables/gyptest-rules-variables.py create mode 100644 tools/gyp/test/rules/variables/src/input_ext.c create mode 100644 tools/gyp/test/rules/variables/src/input_name/test.c create mode 100644 tools/gyp/test/rules/variables/src/input_path/subdir/test.c create mode 100644 tools/gyp/test/rules/variables/src/subdir/input_dirname.c create mode 100644 tools/gyp/test/rules/variables/src/subdir/test.c create mode 100644 tools/gyp/test/rules/variables/src/test.input_root.c create mode 100644 tools/gyp/test/rules/variables/src/variables.gyp create mode 100644 tools/gyp/test/same-gyp-name/gyptest-all.py create mode 100644 tools/gyp/test/same-gyp-name/gyptest-default.py create mode 100644 tools/gyp/test/same-gyp-name/gyptest-library.py create mode 100644 tools/gyp/test/same-gyp-name/library/one/sub.gyp create mode 100644 tools/gyp/test/same-gyp-name/library/test.gyp create mode 100644 tools/gyp/test/same-gyp-name/library/two/sub.gyp create mode 100644 tools/gyp/test/same-gyp-name/src/all.gyp create mode 100644 tools/gyp/test/same-gyp-name/src/subdir1/executable.gyp create mode 100644 tools/gyp/test/same-gyp-name/src/subdir1/main1.cc create mode 100644 tools/gyp/test/same-gyp-name/src/subdir2/executable.gyp create mode 100644 tools/gyp/test/same-gyp-name/src/subdir2/main2.cc create mode 100644 tools/gyp/test/same-rule-output-file-name/gyptest-all.py create mode 100644 tools/gyp/test/same-rule-output-file-name/src/subdir1/subdir1.gyp create mode 100644 tools/gyp/test/same-rule-output-file-name/src/subdir2/subdir2.gyp create mode 100644 tools/gyp/test/same-rule-output-file-name/src/subdirs.gyp create mode 100644 tools/gyp/test/same-rule-output-file-name/src/touch.py create mode 100644 tools/gyp/test/same-source-file-name/gyptest-all.py create mode 100644 tools/gyp/test/same-source-file-name/gyptest-default.py create mode 100644 tools/gyp/test/same-source-file-name/gyptest-pass-executable.py create mode 100644 tools/gyp/test/same-source-file-name/gyptest-pass-shared.py create mode 100644 tools/gyp/test/same-source-file-name/gyptest-static.py create mode 100644 tools/gyp/test/same-source-file-name/src/all.gyp create mode 100644 tools/gyp/test/same-source-file-name/src/double-executable.gyp create mode 100644 tools/gyp/test/same-source-file-name/src/double-shared.gyp create mode 100644 tools/gyp/test/same-source-file-name/src/double-static.gyp create mode 100644 tools/gyp/test/same-source-file-name/src/func.c create mode 100644 tools/gyp/test/same-source-file-name/src/prog1.c create mode 100644 tools/gyp/test/same-source-file-name/src/prog2.c create mode 100644 tools/gyp/test/same-source-file-name/src/prog3.c create mode 100644 tools/gyp/test/same-source-file-name/src/subdir1/func.c create mode 100644 tools/gyp/test/same-source-file-name/src/subdir2/func.c create mode 100644 tools/gyp/test/same-target-name-different-directory/gyptest-all.py create mode 100644 tools/gyp/test/same-target-name-different-directory/src/subdir1/subdir1.gyp create mode 100644 tools/gyp/test/same-target-name-different-directory/src/subdir2/subdir2.gyp create mode 100644 tools/gyp/test/same-target-name-different-directory/src/subdirs.gyp create mode 100644 tools/gyp/test/same-target-name-different-directory/src/touch.py create mode 100644 tools/gyp/test/same-target-name/gyptest-same-target-name.py create mode 100644 tools/gyp/test/same-target-name/src/all.gyp create mode 100644 tools/gyp/test/same-target-name/src/executable1.gyp create mode 100644 tools/gyp/test/same-target-name/src/executable2.gyp create mode 100644 tools/gyp/test/sanitize-rule-names/blah.S create mode 100644 tools/gyp/test/sanitize-rule-names/gyptest-sanitize-rule-names.py create mode 100644 tools/gyp/test/sanitize-rule-names/hello.cc create mode 100644 tools/gyp/test/sanitize-rule-names/sanitize-rule-names.gyp create mode 100644 tools/gyp/test/sanitize-rule-names/script.py create mode 100644 tools/gyp/test/self-dependency/common.gypi create mode 100644 tools/gyp/test/self-dependency/dep.gyp create mode 100644 tools/gyp/test/self-dependency/gyptest-self-dependency.py create mode 100644 tools/gyp/test/self-dependency/self_dependency.gyp create mode 100644 tools/gyp/test/sibling/gyptest-all.py create mode 100644 tools/gyp/test/sibling/gyptest-relocate.py create mode 100644 tools/gyp/test/sibling/src/build/all.gyp create mode 100644 tools/gyp/test/sibling/src/prog1/prog1.c create mode 100644 tools/gyp/test/sibling/src/prog1/prog1.gyp create mode 100644 tools/gyp/test/sibling/src/prog2/prog2.c create mode 100644 tools/gyp/test/sibling/src/prog2/prog2.gyp create mode 100644 tools/gyp/test/small/gyptest-small.py create mode 100644 tools/gyp/test/standalone-static-library/gyptest-standalone-static-library.py create mode 100644 tools/gyp/test/standalone-static-library/invalid.gyp create mode 100644 tools/gyp/test/standalone-static-library/mylib.c create mode 100644 tools/gyp/test/standalone-static-library/mylib.gyp create mode 100644 tools/gyp/test/standalone-static-library/prog.c create mode 100644 tools/gyp/test/standalone/gyptest-standalone.py create mode 100644 tools/gyp/test/standalone/standalone.gyp create mode 100644 tools/gyp/test/subdirectory/gyptest-SYMROOT-all.py create mode 100644 tools/gyp/test/subdirectory/gyptest-SYMROOT-default.py create mode 100644 tools/gyp/test/subdirectory/gyptest-subdir-all.py create mode 100644 tools/gyp/test/subdirectory/gyptest-subdir-default.py create mode 100644 tools/gyp/test/subdirectory/gyptest-subdir2-deep.py create mode 100644 tools/gyp/test/subdirectory/gyptest-top-all.py create mode 100644 tools/gyp/test/subdirectory/gyptest-top-default.py create mode 100644 tools/gyp/test/subdirectory/src/prog1.c create mode 100644 tools/gyp/test/subdirectory/src/prog1.gyp create mode 100644 tools/gyp/test/subdirectory/src/subdir/prog2.c create mode 100644 tools/gyp/test/subdirectory/src/subdir/prog2.gyp create mode 100644 tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.c create mode 100644 tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.gyp create mode 100644 tools/gyp/test/subdirectory/src/symroot.gypi create mode 100644 tools/gyp/test/symlinks/gyptest-symlinks.py create mode 100644 tools/gyp/test/symlinks/hello.c create mode 100644 tools/gyp/test/symlinks/hello.gyp create mode 100644 tools/gyp/test/target/gyptest-target.py create mode 100644 tools/gyp/test/target/hello.c create mode 100644 tools/gyp/test/target/target.gyp create mode 100644 tools/gyp/test/toolsets/gyptest-toolsets.py create mode 100644 tools/gyp/test/toolsets/main.cc create mode 100644 tools/gyp/test/toolsets/toolsets.cc create mode 100644 tools/gyp/test/toolsets/toolsets.gyp create mode 100644 tools/gyp/test/toolsets/toolsets_shared.cc create mode 100644 tools/gyp/test/toplevel-dir/gyptest-toplevel-dir.py create mode 100644 tools/gyp/test/toplevel-dir/src/sub1/main.gyp create mode 100644 tools/gyp/test/toplevel-dir/src/sub1/prog1.c create mode 100644 tools/gyp/test/toplevel-dir/src/sub2/prog2.c create mode 100644 tools/gyp/test/toplevel-dir/src/sub2/prog2.gyp create mode 100644 tools/gyp/test/variables/commands/commands-repeated.gyp create mode 100644 tools/gyp/test/variables/commands/commands-repeated.gyp.stdout create mode 100644 tools/gyp/test/variables/commands/commands-repeated.gypd.golden create mode 100644 tools/gyp/test/variables/commands/commands.gyp create mode 100644 tools/gyp/test/variables/commands/commands.gyp.ignore-env.stdout create mode 100644 tools/gyp/test/variables/commands/commands.gyp.stdout create mode 100644 tools/gyp/test/variables/commands/commands.gypd.golden create mode 100644 tools/gyp/test/variables/commands/commands.gypi create mode 100644 tools/gyp/test/variables/commands/gyptest-commands-ignore-env.py create mode 100644 tools/gyp/test/variables/commands/gyptest-commands-repeated-multidir.py create mode 100644 tools/gyp/test/variables/commands/gyptest-commands-repeated.py create mode 100644 tools/gyp/test/variables/commands/gyptest-commands.py create mode 100644 tools/gyp/test/variables/commands/repeated_multidir/dir_1/test_1.gyp create mode 100644 tools/gyp/test/variables/commands/repeated_multidir/dir_2/test_2.gyp create mode 100644 tools/gyp/test/variables/commands/repeated_multidir/main.gyp create mode 100644 tools/gyp/test/variables/commands/repeated_multidir/print_cwd_basename.py create mode 100644 tools/gyp/test/variables/commands/repeated_multidir/repeated_command_common.gypi create mode 100644 tools/gyp/test/variables/commands/test.py create mode 100644 tools/gyp/test/variables/commands/update_golden create mode 100644 tools/gyp/test/variables/empty/empty.gyp create mode 100644 tools/gyp/test/variables/empty/empty.gypi create mode 100644 tools/gyp/test/variables/empty/gyptest-empty.py create mode 100644 tools/gyp/test/variables/filelist/filelist.gyp.stdout create mode 100644 tools/gyp/test/variables/filelist/filelist.gypd.golden create mode 100644 tools/gyp/test/variables/filelist/gyptest-filelist-golden.py create mode 100644 tools/gyp/test/variables/filelist/gyptest-filelist.py create mode 100644 tools/gyp/test/variables/filelist/src/dummy.py create mode 100644 tools/gyp/test/variables/filelist/src/filelist.gyp create mode 100644 tools/gyp/test/variables/filelist/src/filelist2.gyp create mode 100644 tools/gyp/test/variables/filelist/update_golden create mode 100644 tools/gyp/test/variables/latelate/gyptest-latelate.py create mode 100644 tools/gyp/test/variables/latelate/src/latelate.gyp create mode 100644 tools/gyp/test/variables/latelate/src/program.cc create mode 100644 tools/gyp/test/variables/variable-in-path/C1/hello.cc create mode 100644 tools/gyp/test/variables/variable-in-path/gyptest-variable-in-path.py create mode 100644 tools/gyp/test/variables/variable-in-path/variable-in-path.gyp create mode 100644 tools/gyp/test/win/asm-files/asm-files.gyp create mode 100644 tools/gyp/test/win/asm-files/b.s create mode 100644 tools/gyp/test/win/asm-files/c.S create mode 100644 tools/gyp/test/win/asm-files/hello.cc create mode 100644 tools/gyp/test/win/batch-file-action/batch-file-action.gyp create mode 100644 tools/gyp/test/win/batch-file-action/infile create mode 100644 tools/gyp/test/win/batch-file-action/somecmd.bat create mode 100644 tools/gyp/test/win/command-quote/a.S create mode 100644 tools/gyp/test/win/command-quote/bat with spaces.bat create mode 100644 tools/gyp/test/win/command-quote/command-quote.gyp create mode 100644 tools/gyp/test/win/command-quote/go.bat create mode 100644 tools/gyp/test/win/command-quote/subdir/and/another/in-subdir.gyp create mode 100644 tools/gyp/test/win/compiler-flags/additional-include-dirs.cc create mode 100644 tools/gyp/test/win/compiler-flags/additional-include-dirs.gyp create mode 100644 tools/gyp/test/win/compiler-flags/additional-options.cc create mode 100644 tools/gyp/test/win/compiler-flags/additional-options.gyp create mode 100644 tools/gyp/test/win/compiler-flags/analysis.gyp create mode 100644 tools/gyp/test/win/compiler-flags/buffer-security-check.gyp create mode 100644 tools/gyp/test/win/compiler-flags/buffer-security.cc create mode 100644 tools/gyp/test/win/compiler-flags/calling-convention-cdecl.def create mode 100644 tools/gyp/test/win/compiler-flags/calling-convention-fastcall.def create mode 100644 tools/gyp/test/win/compiler-flags/calling-convention-stdcall.def create mode 100644 tools/gyp/test/win/compiler-flags/calling-convention-vectorcall.def create mode 100644 tools/gyp/test/win/compiler-flags/calling-convention.cc create mode 100644 tools/gyp/test/win/compiler-flags/calling-convention.gyp create mode 100644 tools/gyp/test/win/compiler-flags/character-set-mbcs.cc create mode 100644 tools/gyp/test/win/compiler-flags/character-set-unicode.cc create mode 100644 tools/gyp/test/win/compiler-flags/character-set.gyp create mode 100644 tools/gyp/test/win/compiler-flags/compile-as-managed.cc create mode 100644 tools/gyp/test/win/compiler-flags/compile-as-managed.gyp create mode 100644 tools/gyp/test/win/compiler-flags/compile-as-winrt.cc create mode 100644 tools/gyp/test/win/compiler-flags/compile-as-winrt.gyp create mode 100644 tools/gyp/test/win/compiler-flags/debug-format.gyp create mode 100644 tools/gyp/test/win/compiler-flags/default-char-is-unsigned.cc create mode 100644 tools/gyp/test/win/compiler-flags/default-char-is-unsigned.gyp create mode 100644 tools/gyp/test/win/compiler-flags/disable-specific-warnings.cc create mode 100644 tools/gyp/test/win/compiler-flags/disable-specific-warnings.gyp create mode 100644 tools/gyp/test/win/compiler-flags/enable-enhanced-instruction-set.cc create mode 100644 tools/gyp/test/win/compiler-flags/enable-enhanced-instruction-set.gyp create mode 100644 tools/gyp/test/win/compiler-flags/exception-handling-on.cc create mode 100644 tools/gyp/test/win/compiler-flags/exception-handling.gyp create mode 100644 tools/gyp/test/win/compiler-flags/floating-point-model-fast.cc create mode 100644 tools/gyp/test/win/compiler-flags/floating-point-model-precise.cc create mode 100644 tools/gyp/test/win/compiler-flags/floating-point-model-strict.cc create mode 100644 tools/gyp/test/win/compiler-flags/floating-point-model.gyp create mode 100644 tools/gyp/test/win/compiler-flags/force-include-files-with-precompiled.cc create mode 100644 tools/gyp/test/win/compiler-flags/force-include-files.cc create mode 100644 tools/gyp/test/win/compiler-flags/force-include-files.gyp create mode 100644 tools/gyp/test/win/compiler-flags/function-level-linking.cc create mode 100644 tools/gyp/test/win/compiler-flags/function-level-linking.gyp create mode 100644 tools/gyp/test/win/compiler-flags/hello.cc create mode 100644 tools/gyp/test/win/compiler-flags/optimizations.gyp create mode 100644 tools/gyp/test/win/compiler-flags/pdbname-override.gyp create mode 100644 tools/gyp/test/win/compiler-flags/pdbname.cc create mode 100644 tools/gyp/test/win/compiler-flags/pdbname.gyp create mode 100644 tools/gyp/test/win/compiler-flags/precomp.cc create mode 100644 tools/gyp/test/win/compiler-flags/rtti-on.cc create mode 100644 tools/gyp/test/win/compiler-flags/rtti.gyp create mode 100644 tools/gyp/test/win/compiler-flags/runtime-checks.cc create mode 100644 tools/gyp/test/win/compiler-flags/runtime-checks.gyp create mode 100644 tools/gyp/test/win/compiler-flags/runtime-library-md.cc create mode 100644 tools/gyp/test/win/compiler-flags/runtime-library-mdd.cc create mode 100644 tools/gyp/test/win/compiler-flags/runtime-library-mt.cc create mode 100644 tools/gyp/test/win/compiler-flags/runtime-library-mtd.cc create mode 100644 tools/gyp/test/win/compiler-flags/runtime-library.gyp create mode 100644 tools/gyp/test/win/compiler-flags/subdir/header.h create mode 100644 tools/gyp/test/win/compiler-flags/treat-wchar-t-as-built-in-type.gyp create mode 100644 tools/gyp/test/win/compiler-flags/treat-wchar-t-as-built-in-type1.cc create mode 100644 tools/gyp/test/win/compiler-flags/treat-wchar-t-as-built-in-type2.cc create mode 100644 tools/gyp/test/win/compiler-flags/uninit.cc create mode 100644 tools/gyp/test/win/compiler-flags/warning-as-error.cc create mode 100644 tools/gyp/test/win/compiler-flags/warning-as-error.gyp create mode 100644 tools/gyp/test/win/compiler-flags/warning-level.gyp create mode 100644 tools/gyp/test/win/compiler-flags/warning-level1.cc create mode 100644 tools/gyp/test/win/compiler-flags/warning-level2.cc create mode 100644 tools/gyp/test/win/compiler-flags/warning-level3.cc create mode 100644 tools/gyp/test/win/compiler-flags/warning-level4.cc create mode 100644 tools/gyp/test/win/enable-winrt/dllmain.cc create mode 100644 tools/gyp/test/win/enable-winrt/enable-winrt.gyp create mode 100644 tools/gyp/test/win/generator-output-different-drive/gyptest-generator-output-different-drive.py create mode 100644 tools/gyp/test/win/generator-output-different-drive/prog.c rename tools/gyp/{gyp => test/win/generator-output-different-drive/prog.gyp} (53%) mode change 100755 => 100644 create mode 100644 tools/gyp/test/win/gyptest-asm-files.py create mode 100644 tools/gyp/test/win/gyptest-cl-additional-include-dirs.py create mode 100644 tools/gyp/test/win/gyptest-cl-additional-options.py create mode 100644 tools/gyp/test/win/gyptest-cl-analysis.py create mode 100644 tools/gyp/test/win/gyptest-cl-buffer-security-check.py create mode 100644 tools/gyp/test/win/gyptest-cl-calling-convention.py create mode 100644 tools/gyp/test/win/gyptest-cl-character-set.py create mode 100644 tools/gyp/test/win/gyptest-cl-compile-as-managed.py create mode 100644 tools/gyp/test/win/gyptest-cl-compile-as-winrt.py create mode 100644 tools/gyp/test/win/gyptest-cl-debug-format.py create mode 100644 tools/gyp/test/win/gyptest-cl-default-char-is-unsigned.py create mode 100644 tools/gyp/test/win/gyptest-cl-disable-specific-warnings.py create mode 100644 tools/gyp/test/win/gyptest-cl-enable-enhanced-instruction-set.py create mode 100644 tools/gyp/test/win/gyptest-cl-exception-handling.py create mode 100644 tools/gyp/test/win/gyptest-cl-floating-point-model.py create mode 100644 tools/gyp/test/win/gyptest-cl-force-include-files.py create mode 100644 tools/gyp/test/win/gyptest-cl-function-level-linking.py create mode 100644 tools/gyp/test/win/gyptest-cl-optimizations.py create mode 100644 tools/gyp/test/win/gyptest-cl-pdbname-override.py create mode 100644 tools/gyp/test/win/gyptest-cl-pdbname.py create mode 100644 tools/gyp/test/win/gyptest-cl-rtti.py create mode 100644 tools/gyp/test/win/gyptest-cl-runtime-checks.py create mode 100644 tools/gyp/test/win/gyptest-cl-runtime-library.py create mode 100644 tools/gyp/test/win/gyptest-cl-treat-wchar-t-as-built-in-type.py create mode 100644 tools/gyp/test/win/gyptest-cl-warning-as-error.py create mode 100644 tools/gyp/test/win/gyptest-cl-warning-level.py create mode 100644 tools/gyp/test/win/gyptest-command-quote.py create mode 100644 tools/gyp/test/win/gyptest-crosscompile-ar.py create mode 100644 tools/gyp/test/win/gyptest-lib-ltcg.py create mode 100644 tools/gyp/test/win/gyptest-link-additional-deps.py create mode 100644 tools/gyp/test/win/gyptest-link-additional-options.py create mode 100644 tools/gyp/test/win/gyptest-link-aslr.py create mode 100644 tools/gyp/test/win/gyptest-link-base-address.py create mode 100644 tools/gyp/test/win/gyptest-link-debug-info.py create mode 100644 tools/gyp/test/win/gyptest-link-default-libs.py create mode 100644 tools/gyp/test/win/gyptest-link-deffile.py create mode 100644 tools/gyp/test/win/gyptest-link-defrelink.py create mode 100644 tools/gyp/test/win/gyptest-link-delay-load-dlls.py create mode 100644 tools/gyp/test/win/gyptest-link-embed-manifest.py create mode 100644 tools/gyp/test/win/gyptest-link-enable-uac.py create mode 100644 tools/gyp/test/win/gyptest-link-enable-winrt-app-revision.py create mode 100644 tools/gyp/test/win/gyptest-link-enable-winrt-target-platform-version.py create mode 100644 tools/gyp/test/win/gyptest-link-enable-winrt.py create mode 100644 tools/gyp/test/win/gyptest-link-entrypointsymbol.py create mode 100644 tools/gyp/test/win/gyptest-link-fixed-base.py create mode 100644 tools/gyp/test/win/gyptest-link-force-symbol-reference.py create mode 100644 tools/gyp/test/win/gyptest-link-generate-manifest.py create mode 100644 tools/gyp/test/win/gyptest-link-incremental.py create mode 100644 tools/gyp/test/win/gyptest-link-large-address-aware.py create mode 100644 tools/gyp/test/win/gyptest-link-large-pdb.py create mode 100644 tools/gyp/test/win/gyptest-link-library-adjust.py create mode 100644 tools/gyp/test/win/gyptest-link-library-directories.py create mode 100644 tools/gyp/test/win/gyptest-link-ltcg.py create mode 100644 tools/gyp/test/win/gyptest-link-mapfile.py create mode 100644 tools/gyp/test/win/gyptest-link-nodefaultlib.py create mode 100644 tools/gyp/test/win/gyptest-link-noimportlib.py create mode 100644 tools/gyp/test/win/gyptest-link-nxcompat.py create mode 100644 tools/gyp/test/win/gyptest-link-opt-icf.py create mode 100644 tools/gyp/test/win/gyptest-link-opt-ref.py create mode 100644 tools/gyp/test/win/gyptest-link-ordering.py create mode 100644 tools/gyp/test/win/gyptest-link-outputfile.py create mode 100644 tools/gyp/test/win/gyptest-link-pdb-no-output.py create mode 100644 tools/gyp/test/win/gyptest-link-pdb-output.py create mode 100644 tools/gyp/test/win/gyptest-link-pdb.py create mode 100644 tools/gyp/test/win/gyptest-link-pgo.py create mode 100644 tools/gyp/test/win/gyptest-link-profile.py create mode 100644 tools/gyp/test/win/gyptest-link-restat-importlib.py create mode 100644 tools/gyp/test/win/gyptest-link-safeseh.py create mode 100644 tools/gyp/test/win/gyptest-link-shard.py create mode 100644 tools/gyp/test/win/gyptest-link-stacksize.py create mode 100644 tools/gyp/test/win/gyptest-link-subsystem.py create mode 100644 tools/gyp/test/win/gyptest-link-target-machine.py create mode 100644 tools/gyp/test/win/gyptest-link-tsaware.py create mode 100644 tools/gyp/test/win/gyptest-link-uldi-depending-on-module.py create mode 100644 tools/gyp/test/win/gyptest-link-uldi.py create mode 100644 tools/gyp/test/win/gyptest-link-unsupported-manifest.py create mode 100644 tools/gyp/test/win/gyptest-link-update-manifest.py create mode 100644 tools/gyp/test/win/gyptest-link-warnings-as-errors.py create mode 100644 tools/gyp/test/win/gyptest-long-command-line.py create mode 100644 tools/gyp/test/win/gyptest-macro-projectname.py create mode 100644 tools/gyp/test/win/gyptest-macro-targetext.py create mode 100644 tools/gyp/test/win/gyptest-macro-targetfilename.py create mode 100644 tools/gyp/test/win/gyptest-macro-targetname.py create mode 100644 tools/gyp/test/win/gyptest-macro-targetpath.py create mode 100644 tools/gyp/test/win/gyptest-macro-vcinstalldir.py create mode 100644 tools/gyp/test/win/gyptest-macros-containing-gyp.py create mode 100644 tools/gyp/test/win/gyptest-macros-in-inputs-and-outputs.py create mode 100644 tools/gyp/test/win/gyptest-midl-excluded.py create mode 100644 tools/gyp/test/win/gyptest-midl-includedirs.py create mode 100644 tools/gyp/test/win/gyptest-midl-rules.py create mode 100644 tools/gyp/test/win/gyptest-ml-safeseh.py create mode 100644 tools/gyp/test/win/gyptest-quoting-commands.py create mode 100644 tools/gyp/test/win/gyptest-rc-build.py create mode 100644 tools/gyp/test/win/gyptest-sys.py create mode 100644 tools/gyp/test/win/gyptest-system-include.py create mode 100644 tools/gyp/test/win/idl-excluded/bad.idl create mode 100644 tools/gyp/test/win/idl-excluded/copy-file.py create mode 100644 tools/gyp/test/win/idl-excluded/idl-excluded.gyp create mode 100644 tools/gyp/test/win/idl-excluded/program.cc create mode 100644 tools/gyp/test/win/idl-includedirs/hello.cc create mode 100644 tools/gyp/test/win/idl-includedirs/idl-includedirs.gyp create mode 100644 tools/gyp/test/win/idl-includedirs/subdir/bar.idl create mode 100644 tools/gyp/test/win/idl-includedirs/subdir/foo.idl create mode 100644 tools/gyp/test/win/idl-rules/Window.idl create mode 100644 tools/gyp/test/win/idl-rules/basic-idl.gyp create mode 100644 tools/gyp/test/win/idl-rules/history_indexer.idl create mode 100644 tools/gyp/test/win/idl-rules/history_indexer_user.cc create mode 100644 tools/gyp/test/win/idl-rules/idl_compiler.py create mode 100644 tools/gyp/test/win/importlib/dll_no_exports.cc create mode 100644 tools/gyp/test/win/importlib/has-exports.cc create mode 100644 tools/gyp/test/win/importlib/hello.cc create mode 100644 tools/gyp/test/win/importlib/importlib.gyp create mode 100644 tools/gyp/test/win/importlib/noimplib.gyp create mode 100644 tools/gyp/test/win/large-pdb/dllmain.cc create mode 100644 tools/gyp/test/win/large-pdb/large-pdb.gyp create mode 100644 tools/gyp/test/win/large-pdb/main.cc create mode 100644 tools/gyp/test/win/lib-crosscompile/answer.cc create mode 100644 tools/gyp/test/win/lib-crosscompile/answer.h create mode 100644 tools/gyp/test/win/lib-crosscompile/use_host_ar.gyp create mode 100644 tools/gyp/test/win/lib-flags/answer.cc create mode 100644 tools/gyp/test/win/lib-flags/answer.h create mode 100644 tools/gyp/test/win/lib-flags/ltcg.gyp create mode 100644 tools/gyp/test/win/linker-flags/a/x.cc create mode 100644 tools/gyp/test/win/linker-flags/a/z.cc create mode 100644 tools/gyp/test/win/linker-flags/additional-deps.cc create mode 100644 tools/gyp/test/win/linker-flags/additional-deps.gyp create mode 100644 tools/gyp/test/win/linker-flags/additional-options.gyp create mode 100644 tools/gyp/test/win/linker-flags/aslr.gyp create mode 100644 tools/gyp/test/win/linker-flags/b/y.cc create mode 100644 tools/gyp/test/win/linker-flags/base-address.gyp create mode 100644 tools/gyp/test/win/linker-flags/debug-info.gyp create mode 100644 tools/gyp/test/win/linker-flags/deffile-multiple.gyp create mode 100644 tools/gyp/test/win/linker-flags/deffile.cc create mode 100644 tools/gyp/test/win/linker-flags/deffile.def create mode 100644 tools/gyp/test/win/linker-flags/deffile.gyp create mode 100644 tools/gyp/test/win/linker-flags/delay-load-dlls.gyp create mode 100644 tools/gyp/test/win/linker-flags/delay-load.cc create mode 100644 tools/gyp/test/win/linker-flags/embed-manifest.gyp create mode 100644 tools/gyp/test/win/linker-flags/enable-uac.gyp create mode 100644 tools/gyp/test/win/linker-flags/entrypointsymbol.cc create mode 100644 tools/gyp/test/win/linker-flags/entrypointsymbol.gyp create mode 100644 tools/gyp/test/win/linker-flags/extra.manifest create mode 100644 tools/gyp/test/win/linker-flags/extra2.manifest create mode 100644 tools/gyp/test/win/linker-flags/fixed-base.gyp create mode 100644 tools/gyp/test/win/linker-flags/force-symbol-reference.gyp create mode 100644 tools/gyp/test/win/linker-flags/generate-manifest.gyp create mode 100644 tools/gyp/test/win/linker-flags/hello.cc create mode 100644 tools/gyp/test/win/linker-flags/incremental.gyp create mode 100644 tools/gyp/test/win/linker-flags/inline_test.cc create mode 100644 tools/gyp/test/win/linker-flags/inline_test.h create mode 100644 tools/gyp/test/win/linker-flags/inline_test_main.cc create mode 100644 tools/gyp/test/win/linker-flags/large-address-aware.gyp create mode 100644 tools/gyp/test/win/linker-flags/library-adjust.cc create mode 100644 tools/gyp/test/win/linker-flags/library-adjust.gyp create mode 100644 tools/gyp/test/win/linker-flags/library-directories-define.cc create mode 100644 tools/gyp/test/win/linker-flags/library-directories-reference.cc create mode 100644 tools/gyp/test/win/linker-flags/library-directories.gyp create mode 100644 tools/gyp/test/win/linker-flags/link-ordering.gyp create mode 100644 tools/gyp/test/win/linker-flags/link-warning.cc create mode 100644 tools/gyp/test/win/linker-flags/ltcg.gyp create mode 100644 tools/gyp/test/win/linker-flags/main-crt.c create mode 100644 tools/gyp/test/win/linker-flags/manifest-in-comment.cc create mode 100644 tools/gyp/test/win/linker-flags/mapfile.cc create mode 100644 tools/gyp/test/win/linker-flags/mapfile.gyp create mode 100644 tools/gyp/test/win/linker-flags/no-default-libs.cc create mode 100644 tools/gyp/test/win/linker-flags/no-default-libs.gyp create mode 100644 tools/gyp/test/win/linker-flags/nodefaultlib.cc create mode 100644 tools/gyp/test/win/linker-flags/nodefaultlib.gyp create mode 100644 tools/gyp/test/win/linker-flags/nxcompat.gyp create mode 100644 tools/gyp/test/win/linker-flags/opt-icf.cc create mode 100644 tools/gyp/test/win/linker-flags/opt-icf.gyp create mode 100644 tools/gyp/test/win/linker-flags/opt-ref.cc create mode 100644 tools/gyp/test/win/linker-flags/opt-ref.gyp create mode 100644 tools/gyp/test/win/linker-flags/outputfile.gyp create mode 100644 tools/gyp/test/win/linker-flags/pdb-output.gyp create mode 100644 tools/gyp/test/win/linker-flags/pgo.gyp create mode 100644 tools/gyp/test/win/linker-flags/profile.gyp create mode 100644 tools/gyp/test/win/linker-flags/program-database.gyp create mode 100644 tools/gyp/test/win/linker-flags/safeseh.gyp create mode 100644 tools/gyp/test/win/linker-flags/safeseh_hello.cc create mode 100644 tools/gyp/test/win/linker-flags/safeseh_zero.asm create mode 100644 tools/gyp/test/win/linker-flags/safeseh_zero64.asm create mode 100644 tools/gyp/test/win/linker-flags/stacksize.gyp create mode 100644 tools/gyp/test/win/linker-flags/subdir/library.gyp create mode 100644 tools/gyp/test/win/linker-flags/subsystem-windows.cc create mode 100644 tools/gyp/test/win/linker-flags/subsystem.gyp create mode 100644 tools/gyp/test/win/linker-flags/target-machine.gyp create mode 100644 tools/gyp/test/win/linker-flags/tsaware.gyp create mode 100644 tools/gyp/test/win/linker-flags/unsupported-manifest.gyp create mode 100644 tools/gyp/test/win/linker-flags/update_pgd.py create mode 100644 tools/gyp/test/win/linker-flags/warn-as-error.gyp create mode 100644 tools/gyp/test/win/linker-flags/x.cc create mode 100644 tools/gyp/test/win/linker-flags/y.cc create mode 100644 tools/gyp/test/win/linker-flags/z.cc create mode 100644 tools/gyp/test/win/long-command-line/function.cc create mode 100644 tools/gyp/test/win/long-command-line/hello.cc create mode 100644 tools/gyp/test/win/long-command-line/long-command-line.gyp create mode 100644 tools/gyp/test/win/ml-safeseh/a.asm create mode 100644 tools/gyp/test/win/ml-safeseh/hello.cc create mode 100644 tools/gyp/test/win/ml-safeseh/ml-safeseh.gyp create mode 100644 tools/gyp/test/win/precompiled/gyptest-all.py create mode 100644 tools/gyp/test/win/precompiled/hello.c create mode 100644 tools/gyp/test/win/precompiled/hello.gyp create mode 100644 tools/gyp/test/win/precompiled/hello2.c create mode 100644 tools/gyp/test/win/precompiled/precomp.c create mode 100644 tools/gyp/test/win/rc-build/Resource.h create mode 100644 tools/gyp/test/win/rc-build/hello.cpp create mode 100644 tools/gyp/test/win/rc-build/hello.gyp create mode 100644 tools/gyp/test/win/rc-build/hello.h create mode 100644 tools/gyp/test/win/rc-build/hello.ico create mode 100644 tools/gyp/test/win/rc-build/hello.rc create mode 100644 tools/gyp/test/win/rc-build/hello3.rc create mode 100644 tools/gyp/test/win/rc-build/small.ico create mode 100644 tools/gyp/test/win/rc-build/subdir/hello2.rc create mode 100644 tools/gyp/test/win/rc-build/subdir/include.h create mode 100644 tools/gyp/test/win/rc-build/targetver.h create mode 100644 tools/gyp/test/win/shard/hello.cc create mode 100644 tools/gyp/test/win/shard/hello1.cc create mode 100644 tools/gyp/test/win/shard/hello2.cc create mode 100644 tools/gyp/test/win/shard/hello3.cc create mode 100644 tools/gyp/test/win/shard/hello4.cc create mode 100644 tools/gyp/test/win/shard/shard.gyp create mode 100644 tools/gyp/test/win/shard/shard_ref.gyp create mode 100644 tools/gyp/test/win/system-include/bar/header.h create mode 100644 tools/gyp/test/win/system-include/common/commonheader.h create mode 100644 tools/gyp/test/win/system-include/foo/header.h create mode 100644 tools/gyp/test/win/system-include/main.cc create mode 100644 tools/gyp/test/win/system-include/test.gyp create mode 100644 tools/gyp/test/win/uldi/a.cc create mode 100644 tools/gyp/test/win/uldi/b.cc create mode 100644 tools/gyp/test/win/uldi/dll.cc create mode 100644 tools/gyp/test/win/uldi/exe.cc create mode 100644 tools/gyp/test/win/uldi/main.cc create mode 100644 tools/gyp/test/win/uldi/uldi-depending-on-module.gyp create mode 100644 tools/gyp/test/win/uldi/uldi.gyp create mode 100644 tools/gyp/test/win/vs-macros/as.py create mode 100644 tools/gyp/test/win/vs-macros/containing-gyp.gyp create mode 100644 tools/gyp/test/win/vs-macros/do_stuff.py create mode 100644 tools/gyp/test/win/vs-macros/hello.cc create mode 100644 tools/gyp/test/win/vs-macros/input-output-macros.gyp create mode 100644 tools/gyp/test/win/vs-macros/input.S create mode 100644 tools/gyp/test/win/vs-macros/projectname.gyp create mode 100644 tools/gyp/test/win/vs-macros/stuff.blah create mode 100644 tools/gyp/test/win/vs-macros/targetext.gyp create mode 100644 tools/gyp/test/win/vs-macros/targetfilename.gyp create mode 100644 tools/gyp/test/win/vs-macros/targetname.gyp create mode 100644 tools/gyp/test/win/vs-macros/targetpath.gyp create mode 100644 tools/gyp/test/win/vs-macros/test_exists.py create mode 100644 tools/gyp/test/win/vs-macros/vcinstalldir.gyp create mode 100644 tools/gyp/test/win/win-driver-target-type/win-driver-target-type.c create mode 100644 tools/gyp/test/win/win-driver-target-type/win-driver-target-type.gyp create mode 100644 tools/gyp/test/win/win-driver-target-type/win-driver-target-type.h create mode 100644 tools/gyp/test/win/win-driver-target-type/win-driver-target-type.rc create mode 100644 tools/gyp/test/win/win-tool/copies_readonly_files.gyp create mode 100644 tools/gyp/test/win/win-tool/gyptest-win-tool-handles-readonly-files.py create mode 100644 tools/gyp/test/win/winrt-app-type-revision/dllmain.cc create mode 100644 tools/gyp/test/win/winrt-app-type-revision/winrt-app-type-revision.gyp create mode 100644 tools/gyp/test/win/winrt-target-platform-version/dllmain.cc create mode 100644 tools/gyp/test/win/winrt-target-platform-version/winrt-target-platform-version.gyp create mode 100644 tools/gyp/test/xcode-ninja/list_excluded/gyptest-all.py create mode 100644 tools/gyp/test/xcode-ninja/list_excluded/hello.cpp create mode 100644 tools/gyp/test/xcode-ninja/list_excluded/hello_exclude.gyp create mode 100644 tools/gyp/test/xcode-ninja/list_excluded/hello_excluded.cpp create mode 100644 tools/gyp/testlib/README.txt create mode 100644 tools/gyp/testlib/SConsLib/TestCmd.py create mode 100644 tools/gyp/testlib/SConsLib/TestCommon.py create mode 100644 tools/gyp/testlib/SConsLib/TestUnit/__init__.py create mode 100644 tools/gyp/testlib/SConsLib/TestUnit/cli.py create mode 100644 tools/gyp/testlib/SConsLib/TestUnit/taprunner.py create mode 100644 tools/gyp/testlib/SConsLib/__init__.py create mode 100644 tools/gyp/testlib/TestGyp.py create mode 100644 tools/gyp/tools/vssetup.powershell/LICENSE.txt create mode 100644 tools/gyp/tools/vssetup.powershell/Microsoft.VisualStudio.Setup.PowerShell.dll create mode 100644 tools/gyp/tools/vssetup.powershell/VSQuery.ps1 create mode 100644 tools/gyp/tools/vssetup.powershell/VSSetup.psd1 create mode 100644 tools/gyp/tools/vssetup.powershell/VSSetup.types.ps1xml create mode 100644 tools/gyp/tools/vssetup.powershell/about_VSSetup.help.txt diff --git a/tools/gyp/.gitignore b/tools/gyp/.gitignore index 0d20b6487c61e7..912cf723b12c1b 100644 --- a/tools/gyp/.gitignore +++ b/tools/gyp/.gitignore @@ -1 +1,4 @@ *.pyc +/out/ +/.venv/ +*.tests diff --git a/tools/gyp/.travis.yml b/tools/gyp/.travis.yml new file mode 100644 index 00000000000000..feed59704faae4 --- /dev/null +++ b/tools/gyp/.travis.yml @@ -0,0 +1,77 @@ +linux-setup-steps: &linux-setup-steps + dist: xenial # required for Python >= 3.7 (travis-ci/travis-ci#9069) + os: linux + language: python + install: + - pip install --upgrade pip pipenv + - pipenv install --dev + - sudo apt-get install ninja-build + +windows-setup-steps: &windows-setup-steps + os: windows + language: shell # 'language: python' is not yet supported on Windows + env: + - PYTHONUNBUFFERED=1 + install: + - pip install --user --upgrade pip pipenv + - pipenv install --dev + +osx-setup-steps: &osx-setup-steps + os: osx + language: cpp # 'language: python' is not yet supported on macOS + # before_install: brew upgrade python # takes too long + install: + - HOMEBREW_NO_AUTO_UPDATE=1 brew install ninja + - pip install --upgrade pip pipenv + - pipenv install --dev + - pipenv install PyObjC # This is not in the Pipfile because it breaks other platforms https://github.com/pypa/pipenv/issues/3187 + +matrix: + include: + - name: "Linux: test with make and ninja on Python 3.7" + python: '3.7' + <<: *linux-setup-steps + script: pipenv run -v test -f make,ninja + + - name: "Linux: test with make and ninja on Python 2.7" + python: '2.7' + <<: *linux-setup-steps + script: pipenv run -v test -f make,ninja + + - name: "Windows: test on Python 3 with VS2019 Build Tools" + <<: *windows-setup-steps + env: + - GYP_MSVS_VERSION=2019 + - PATH=/c/Python37:/c/Python37/Scripts:/C/Users/travis/AppData/Roaming/Python/Python37/Scripts:$PATH + before_install: + - choco install python3 visualstudio2019buildtools visualstudio2019-workload-vctools + script: pipenv run -v test -f msvs + +# - name: "Windows: test on Python 2 with VS2017 Build Tools" +# <<: *windows-setup-steps +# env: +# - GYP_MSVS_VERSION=2017 +# - GYP_BUILD_TOOL=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe +# - PATH=/c/Python27:/c/Python27/Scripts:/C/Users/travis/AppData/Roaming/Python/Scripts:$PATH +# before_install: +# - choco install python2 visualstudio2017buildtools visualstudio2017-workload-vctools +# script: +# - ls -la tools/vssetup.powershell +# - pipenv run -v test -f msvs + + - name: "macOS: test with make and ninja on Python 3.7" + <<: *osx-setup-steps + script: pipenv run -v test -f make,ninja + + - name: "lint with Python 2.7" + python: '2.7' + <<: *linux-setup-steps + script: pipenv run -v lint + + - name: "lint with Python 3.7" + python: '3.7' + <<: *linux-setup-steps + script: pipenv run -v lint + +notifications: + slack: node4good:C2EI9vo04FY8Ce5u7kcOLlDw diff --git a/tools/gyp/AUTHORS b/tools/gyp/AUTHORS deleted file mode 100644 index 130c8160589364..00000000000000 --- a/tools/gyp/AUTHORS +++ /dev/null @@ -1,15 +0,0 @@ -# Names should be added to this file like so: -# Name or Organization - -Google Inc. <*@google.com> -Bloomberg Finance L.P. <*@bloomberg.net> -IBM Inc. <*@*.ibm.com> -Yandex LLC <*@yandex-team.ru> - -Steven Knight -Ryan Norton -David J. Sankel -Eric N. Vander Weele -Tom Freudenberg -Julien Brianceau -Refael Ackermann diff --git a/tools/gyp/DEPS b/tools/gyp/DEPS deleted file mode 100644 index 167fb779b0e1be..00000000000000 --- a/tools/gyp/DEPS +++ /dev/null @@ -1,23 +0,0 @@ -# DEPS file for gclient use in buildbot execution of gyp tests. -# -# (You don't need to use gclient for normal GYP development work.) - -vars = { - "chromium_git": "https://chromium.googlesource.com/", -} - -deps = { -} - -deps_os = { - "win": { - "third_party/cygwin": - Var("chromium_git") + "chromium/deps/cygwin@4fbd5b9", - - "third_party/python_26": - Var("chromium_git") + "chromium/deps/python_26@5bb4080", - - "src/third_party/pefile": - Var("chromium_git") + "external/pefile@72c6ae4", - }, -} diff --git a/tools/gyp/LICENSE b/tools/gyp/LICENSE index ab6b011a109335..06544248d3c505 100644 --- a/tools/gyp/LICENSE +++ b/tools/gyp/LICENSE @@ -1,4 +1,5 @@ Copyright (c) 2009 Google Inc. All rights reserved. +Copyright (c) 2019 Refael Ackermann. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/tools/gyp/OWNERS b/tools/gyp/OWNERS deleted file mode 100644 index 72e8ffc0db8aad..00000000000000 --- a/tools/gyp/OWNERS +++ /dev/null @@ -1 +0,0 @@ -* diff --git a/tools/gyp/PRESUBMIT.py b/tools/gyp/PRESUBMIT.py deleted file mode 100644 index 4bc1b8ca26afda..00000000000000 --- a/tools/gyp/PRESUBMIT.py +++ /dev/null @@ -1,126 +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. - - -"""Top-level presubmit script for GYP. - -See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts -for more details about the presubmit API built into gcl. -""" - - -PYLINT_BLACKLIST = [ - # TODO: fix me. - # From SCons, not done in google style. - 'test/lib/TestCmd.py', - 'test/lib/TestCommon.py', - 'test/lib/TestGyp.py', -] - - -PYLINT_DISABLED_WARNINGS = [ - # 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. - 'W0622', - # Some unused variables. - 'W0612', - # Operator not preceded/followed by space. - 'C0323', - 'C0322', - # Unnecessary semicolon. - 'W0301', - # Unused argument. - '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. - 'W0212', - # Bad indent. - 'W0311', - # Line too long. - 'C0301', - # Undefined variable. - 'E0602', - # Not exception type specified. - 'W0702', - # No member of that name. - 'E1101', - # Dangerous default {}. - 'W0102', - # Cyclic import. - 'R0401', - # Others, too many to sort. - 'W0201', 'W0232', 'E1103', 'W0621', 'W0108', 'W0223', 'W0231', - 'R0201', 'E0101', 'C0321', - # ************* Module copy - # W0104:427,12:_test.odict.__setitem__: Statement seems to have no effect - 'W0104', -] - - -def _LicenseHeader(input_api): - # Accept any year number from 2009 to the current year. - current_year = int(input_api.time.strftime('%Y')) - allowed_years = (str(s) for s in reversed(xrange(2009, current_year + 1))) - - years_re = '(' + '|'.join(allowed_years) + ')' - - # The (c) is deprecated, but tolerate it until it's removed from all files. - return ( - r'.*? Copyright (\(c\) )?%(year)s Google Inc\. All rights reserved\.\n' - r'.*? Use of this source code is governed by a BSD-style license that ' - r'can be\n' - r'.*? found in the LICENSE file\.\n' - ) % { - 'year': years_re, - } - -def CheckChangeOnUpload(input_api, output_api): - report = [] - report.extend(input_api.canned_checks.PanProjectChecks( - input_api, output_api, license_header=_LicenseHeader(input_api))) - return report - - -def CheckChangeOnCommit(input_api, output_api): - report = [] - - report.extend(input_api.canned_checks.PanProjectChecks( - input_api, output_api, license_header=_LicenseHeader(input_api))) - report.extend(input_api.canned_checks.CheckTreeIsOpen( - input_api, output_api, - '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=blacklist, - disabled_warnings=PYLINT_DISABLED_WARNINGS)) - finally: - sys.path = old_sys_path - return report diff --git a/tools/gyp/Pipfile b/tools/gyp/Pipfile new file mode 100644 index 00000000000000..01cc94808ae29f --- /dev/null +++ b/tools/gyp/Pipfile @@ -0,0 +1,14 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[dev-packages] +flake8 = "*" +pywin32 = { version = "*", sys_platform = "=='win32'" } + +[packages] + +[scripts] +lint = "flake8 . --count --show-source --statistics" +test = "python gyptest.py -a" diff --git a/tools/gyp/Pipfile.lock b/tools/gyp/Pipfile.lock new file mode 100644 index 00000000000000..1b9d8d104ece73 --- /dev/null +++ b/tools/gyp/Pipfile.lock @@ -0,0 +1,70 @@ +{ + "_meta": { + "hash": { + "sha256": "a506a5e632ab6e8dee1ad077d7ef24e4639a263a2cf09960f5a22affd1990de0" + }, + "pipfile-spec": 6, + "requires": {}, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": {}, + "develop": { + "entrypoints": { + "hashes": [ + "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", + "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" + ], + "version": "==0.3" + }, + "flake8": { + "hashes": [ + "sha256:859996073f341f2670741b51ec1e67a01da142831aa1fdc6242dbf88dffbe661", + "sha256:a796a115208f5c03b18f332f7c11729812c8c3ded6c46319c59b53efd3819da8" + ], + "index": "pypi", + "version": "==3.7.7" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "pycodestyle": { + "hashes": [ + "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", + "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" + ], + "version": "==2.5.0" + }, + "pyflakes": { + "hashes": [ + "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", + "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2" + ], + "version": "==2.1.1" + }, + "pywin32": { + "hashes": [ + "sha256:22e218832a54ed206452c8f3ca9eff07ef327f8e597569a4c2828be5eaa09a77", + "sha256:32b37abafbfeddb0fe718008d6aada5a71efa2874f068bee1f9e703983dcc49a", + "sha256:35451edb44162d2f603b5b18bd427bc88fcbc74849eaa7a7e7cfe0f507e5c0c8", + "sha256:4eda2e1e50faa706ff8226195b84fbcbd542b08c842a9b15e303589f85bfb41c", + "sha256:5f265d72588806e134c8e1ede8561739071626ea4cc25c12d526aa7b82416ae5", + "sha256:6852ceac5fdd7a146b570655c37d9eacd520ed1eaeec051ff41c6fc94243d8bf", + "sha256:6dbc4219fe45ece6a0cc6baafe0105604fdee551b5e876dc475d3955b77190ec", + "sha256:9bd07746ce7f2198021a9fa187fa80df7b221ec5e4c234ab6f00ea355a3baf99" + ], + "index": "pypi", + "markers": "sys_platform == 'win32'", + "version": "==224" + } + } +} diff --git a/tools/gyp/README.md b/tools/gyp/README.md index c0d73ac9587af3..55567a907a5d03 100644 --- a/tools/gyp/README.md +++ b/tools/gyp/README.md @@ -1,4 +1,8 @@ -GYP can Generate Your Projects. +[a fork of the unmaintained [google/GYP](https://chromium.googlesource.com/external/gyp)] + +[![Build Status](https://travis-ci.com/refack/GYP.svg?branch=master)](https://travis-ci.com/refack/GYP) + +Generate You Projects =================================== -Documents are available at [gyp.gsrc.io](https://gyp.gsrc.io), or you can check out ```md-pages``` branch to read those documents offline. +Documentation is available at [http://gyp3.org/](http://gyp3.org/) (or at the [`gh-pages`](https://github.com/refack/GYP/blob/gh-pages/index.md) branch). diff --git a/tools/gyp/azure-pipelines.yml b/tools/gyp/azure-pipelines.yml new file mode 100644 index 00000000000000..86db6821d36175 --- /dev/null +++ b/tools/gyp/azure-pipelines.yml @@ -0,0 +1,26 @@ +strategy: + matrix: + # VS2015: + # msvsVersion: '2015' + # imageName: 'vs2015-win2012r2' + VS2017: + msvsVersion: '2017' + imageName: 'vs2017-win2016' + VS2019: + msvsVersion: '2019' + imageName: 'windows-2019' + + +pool: + vmImage: $(imageName) + + +steps: +- task: PythonScript@0 + displayName: 'Run Tests' + env: + GYP_MSVS_VERSION: $(msvsVersion) + inputs: + scriptPath: gyptest.py + arguments: -f msvs -a -v + failOnStderr: false diff --git a/tools/gyp/buildbot/buildbot_run.py b/tools/gyp/buildbot/buildbot_run.py deleted file mode 100755 index 9a2b71f1b355cf..00000000000000 --- a/tools/gyp/buildbot/buildbot_run.py +++ /dev/null @@ -1,136 +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. - -"""Argument-less script to select what to run on the buildbots.""" - -import os -import shutil -import subprocess -import sys - - -BUILDBOT_DIR = os.path.dirname(os.path.abspath(__file__)) -TRUNK_DIR = os.path.dirname(BUILDBOT_DIR) -ROOT_DIR = os.path.dirname(TRUNK_DIR) -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.""" - 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 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 CMake checkout@@@' - shutil.rmtree(CMAKE_DIR) - - # We always build CMake 2.8.8, so no need to do anything - # if the directory already exists. - if os.path.isdir(CMAKE_DIR): - return - - print '@@@BUILD_STEP Initialize CMake checkout@@@' - os.mkdir(CMAKE_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 CMake@@@' - CallSubProcess( - ['/bin/bash', 'bootstrap', '--prefix=%s' % CMAKE_DIR], - cwd=CMAKE_DIR) - - CallSubProcess( ['make', 'cmake'], cwd=CMAKE_DIR) - - -def GypTestFormat(title, format=None, msvs_version=None, tests=[]): - """Run the gyp tests for a given format, emitting annotator tags. - - See annotator docs at: - https://sites.google.com/a/chromium.org/dev/developers/testing/chromium-build-infrastructure/buildbot-annotations - Args: - format: gyp format to test. - Returns: - 0 for sucesss, 1 for failure. - """ - if not format: - format = title - - print '@@@BUILD_STEP ' + title + '@@@' - sys.stdout.flush() - env = os.environ.copy() - if msvs_version: - env['GYP_MSVS_VERSION'] = msvs_version - command = ' '.join( - [sys.executable, 'gyp/gyptest.py', - '--all', - '--passed', - '--format', format, - '--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@@@' - return 1 - return 0 - - -def GypBuild(): - # Dump out/ directory. - print '@@@BUILD_STEP cleanup@@@' - print 'Removing %s...' % OUT_DIR - shutil.rmtree(OUT_DIR, ignore_errors=True) - print 'Done.' - - retcode = 0 - 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') - retcode += GypTestFormat('make') - elif sys.platform == 'win32': - retcode += GypTestFormat('ninja') - if os.environ['BUILDBOT_BUILDERNAME'] == 'gyp-win64': - 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: - # TODO(bradnelson): once the annotator supports a postscript (section for - # after the build proper that could be used for cumulative failures), - # use that instead of this. This isolates the final return value so - # that it isn't misattributed to the last stage. - print '@@@BUILD_STEP failures@@@' - sys.exit(retcode) - - -if __name__ == '__main__': - GypBuild() diff --git a/tools/gyp/buildbot/commit_queue/OWNERS b/tools/gyp/buildbot/commit_queue/OWNERS deleted file mode 100644 index b269c198b43e3e..00000000000000 --- a/tools/gyp/buildbot/commit_queue/OWNERS +++ /dev/null @@ -1,6 +0,0 @@ -set noparent -bradnelson@chromium.org -bradnelson@google.com -iannucci@chromium.org -scottmg@chromium.org -thakis@chromium.org diff --git a/tools/gyp/buildbot/commit_queue/README b/tools/gyp/buildbot/commit_queue/README deleted file mode 100644 index 94284978832702..00000000000000 --- a/tools/gyp/buildbot/commit_queue/README +++ /dev/null @@ -1,3 +0,0 @@ -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 --git a/tools/gyp/buildbot/commit_queue/cq_config.json b/tools/gyp/buildbot/commit_queue/cq_config.json deleted file mode 100644 index 656c21e54fb12f..00000000000000 --- a/tools/gyp/buildbot/commit_queue/cq_config.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "trybots": { - "launched": { - "tryserver.nacl": { - "gyp-presubmit": ["defaulttests"], - "gyp-linux": ["defaulttests"], - "gyp-mac": ["defaulttests"], - "gyp-win32": ["defaulttests"], - "gyp-win64": ["defaulttests"] - } - }, - "triggered": { - } - } -} diff --git a/tools/gyp/codereview.settings b/tools/gyp/codereview.settings deleted file mode 100644 index 27fb9f99e25111..00000000000000 --- a/tools/gyp/codereview.settings +++ /dev/null @@ -1,6 +0,0 @@ -# This file is used by git cl to get repository specific information. -CC_LIST: gyp-developer@googlegroups.com -CODE_REVIEW_SERVER: codereview.chromium.org -GERRIT_HOST: True -PROJECT: gyp -VIEW_VC: https://chromium.googlesource.com/external/gyp/+/ diff --git a/tools/gyp/gyp.bat b/tools/gyp/gyp.bat deleted file mode 100755 index c0b4ca24e5df02..00000000000000 --- a/tools/gyp/gyp.bat +++ /dev/null @@ -1,5 +0,0 @@ -@rem Copyright (c) 2009 Google Inc. All rights reserved. -@rem Use of this source code is governed by a BSD-style license that can be -@rem found in the LICENSE file. - -@python "%~dp0gyp_main.py" %* diff --git a/tools/gyp/pylib/gyp/MSVSNew.py b/tools/gyp/gyp/MSVS/MSVSNew.py similarity index 53% rename from tools/gyp/pylib/gyp/MSVSNew.py rename to tools/gyp/gyp/MSVS/MSVSNew.py index 593f0e5b0b2e88..0381200d08ab3e 100644 --- a/tools/gyp/pylib/gyp/MSVSNew.py +++ b/tools/gyp/gyp/MSVS/MSVSNew.py @@ -4,72 +4,73 @@ """New implementation of Visual Studio project generation.""" +import hashlib import os -import random - import gyp.common -# hashlib is supplied as of Python 2.5 as the replacement interface for md5 -# and other secure hashes. In 2.6, md5 is deprecated. Import hashlib if -# available, avoiding a deprecation warning under 2.6. Import md5 otherwise, -# preserving 2.4 compatibility. -try: - import hashlib - _new_md5 = hashlib.md5 -except ImportError: - import md5 - _new_md5 = md5.new +class MSVSSolutionEntry(object): + """ + Set GUID from path + TODO(rspangler): This is fragile. + 1. We can't just use the project filename sans path, since there could + be multiple projects with the same base name (for example, + foo/unittest.vcproj and bar/unittest.vcproj). + 2. The path needs to be relative to $SOURCE_ROOT, so that the project + GUID is the same whether it's included from base/base.sln or + foo/bar/baz/baz.sln. + 3. The GUID needs to be the same each time this builder is invoked, so + that we don't need to rebuild the solution when the project changes. + 4. We should be able to handle pre-built project files by reading the + GUID from the files. + """ -# Initialize random number generator -random.seed() + guid_seed = "" -# GUIDs for project types -ENTRY_TYPE_GUIDS = { + # GUIDs for project types + ENTRY_TYPE_GUIDS = { 'project': '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}', 'folder': '{2150E333-8FDC-42A3-9474-1A3956D46DE8}', -} - -#------------------------------------------------------------------------------ -# Helper functions - - -def MakeGuid(name, seed='msvs_new'): - """Returns a GUID for the specified target name. + } - Args: - name: Target name. - seed: Seed for MD5 hash. - Returns: - A GUID-line string calculated from the name and seed. - - This generates something which looks like a GUID, but depends only on the - name and seed. This means the same name/seed will always generate the same - GUID, so that projects and solutions which refer to each other can explicitly - determine the GUID to refer to explicitly. It also means that the GUID will - not change when the project for a target is rebuilt. - """ - # Calculate a MD5 signature for the seed and name. - d = _new_md5(str(seed) + str(name)).hexdigest().upper() - # Convert most of the signature to GUID form (discard the rest) - guid = ('{' + d[:8] + '-' + d[8:12] + '-' + d[12:16] + '-' + d[16:20] - + '-' + d[20:32] + '}') - return guid - -#------------------------------------------------------------------------------ + @classmethod + def MakeGuid(cls, name): + """Returns a GUID for the specified target name. + Args: + name: Target name. + Returns: + A GUID-line string calculated from the name and seed. + + This generates something which looks like a GUID, but depends only on the + name and seed. This means the same name/seed will always generate the same + GUID, so that projects and solutions which refer to each other can explicitly + determine the GUID to refer to explicitly. It also means that the GUID will + not change when the project for a target is rebuilt. + """ + # Calculate a MD5 signature for the seed and name. + key = (str(cls.guid_seed) + str(name)).encode('utf-8') + d = hashlib.md5(key).hexdigest().upper() + # Convert most of the signature to GUID form (discard the rest) + guid = ('{' + d[:8] + '-' + d[8:12] + '-' + d[12:16] + '-' + d[16:20] + '-' + d[20:32] + '}') + return guid + + def __init__(self, path, name, guid): + self.path = path + self.name = name + self.guid = guid or MSVSSolutionEntry.MakeGuid(self.path) -class MSVSSolutionEntry(object): - def __cmp__(self, other): + def __lt__(self, other): # Sort by name then guid (so things are in order on vs2008). - return cmp((self.name, self.get_guid()), (other.name, other.get_guid())) + return self.name < other.name -class MSVSFolder(MSVSSolutionEntry): +class MSVSFolderEntry(MSVSSolutionEntry): """Folder in a Visual Studio project or solution.""" - def __init__(self, path, name = None, entries = None, - guid = None, items = None): + guid_seed = 'msvs_folder' + + def __init__(self, path, name=None, entries=None, guid=None, items=None): """Initializes the folder. Args: @@ -81,63 +82,44 @@ def __init__(self, path, name = None, entries = None, items: List of solution items to include in the folder project. May be None, if the folder does not directly contain items. """ - if name: - self.name = name - else: - # Use last layer. - self.name = os.path.basename(path) - + super(MSVSFolderEntry, self).__init__(path, name or os.path.basename(path), guid) self.path = path - self.guid = guid # Copy passed lists (or set to empty lists) self.entries = sorted(list(entries or [])) self.items = list(items or []) - self.entry_type_guid = ENTRY_TYPE_GUIDS['folder'] - - def get_guid(self): - if self.guid is None: - # Use consistent guids for folders (so things don't regenerate). - self.guid = MakeGuid(self.path, seed='msvs_folder') - return self.guid - - -#------------------------------------------------------------------------------ + self.entry_type_guid = self.ENTRY_TYPE_GUIDS['folder'] -class MSVSProject(MSVSSolutionEntry): +class MSVSProjectEntry(MSVSSolutionEntry): """Visual Studio project.""" - def __init__(self, path, name = None, dependencies = None, guid = None, - spec = None, build_file = None, config_platform_overrides = None, - fixpath_prefix = None): + guid_seed = 'msvs_new' + + def __init__(self, path, name=None, dependencies=None, guid=None, spec=None, build_file=None, config_platform_overrides=None, fixpath_prefix=None): """Initializes the project. Args: path: Absolute path to the project file. - name: Name of project. If None, the name will be the same as the base - name of the project file. - dependencies: List of other Project objects this project is dependent - upon, if not None. - guid: GUID to use for project, if not None. + name: Name of project. If None, the name will be the same as the base name of the project file. + dependencies: List of other Project objects this project is dependent upon, if not None. spec: Dictionary specifying how to build this project. build_file: Filename of the .gyp file that the vcproj file comes from. config_platform_overrides: optional dict of configuration platforms to used in place of the default for this target. fixpath_prefix: the path used to adjust the behavior of _fixpath """ - self.path = path - self.guid = guid + + # Use project filename if name not specified + super(MSVSProjectEntry, self).__init__(path, name or os.path.splitext(os.path.basename(path))[0], guid) self.spec = spec self.build_file = build_file - # Use project filename if name not specified - self.name = name or os.path.splitext(os.path.basename(path))[0] # Copy passed lists (or set to empty lists) self.dependencies = list(dependencies or []) - self.entry_type_guid = ENTRY_TYPE_GUIDS['project'] + self.entry_type_guid = self.ENTRY_TYPE_GUIDS['project'] if config_platform_overrides: self.config_platform_overrides = config_platform_overrides @@ -149,34 +131,17 @@ def __init__(self, path, name = None, dependencies = None, guid = None, def set_dependencies(self, dependencies): self.dependencies = list(dependencies or []) - def get_guid(self): - if self.guid is None: - # Set GUID from path - # TODO(rspangler): This is fragile. - # 1. We can't just use the project filename sans path, since there could - # be multiple projects with the same base name (for example, - # foo/unittest.vcproj and bar/unittest.vcproj). - # 2. The path needs to be relative to $SOURCE_ROOT, so that the project - # GUID is the same whether it's included from base/base.sln or - # foo/bar/baz/baz.sln. - # 3. The GUID needs to be the same each time this builder is invoked, so - # that we don't need to rebuild the solution when the project changes. - # 4. We should be able to handle pre-built project files by reading the - # GUID from the files. - self.guid = MakeGuid(self.name) - return self.guid - def set_msbuild_toolset(self, msbuild_toolset): self.msbuild_toolset = msbuild_toolset + #------------------------------------------------------------------------------ class MSVSSolution(object): """Visual Studio solution.""" - def __init__(self, path, version, entries=None, variants=None, - websiteProperties=True): + def __init__(self, path, version, entries=None, variants=None, websiteProperties=True): """Initializes the solution. Args: @@ -202,14 +167,12 @@ def __init__(self, path, version, entries=None, variants=None, else: # Use default self.variants = ['Debug|Win32', 'Release|Win32'] - # TODO(rspangler): Need to be able to handle a mapping of solution config - # to project config. Should we be able to handle variants being a dict, - # or add a separate variant_map variable? If it's a dict, we can't - # guarantee the order of variants since dict keys aren't ordered. + # TODO(rspangler): Need to be able to handle a mapping of solution config to project config. + # Should we be able to handle variants being a dict, or add a separate variant_map variable? + # If it's a dict, we can't guarantee the order of variants since dict keys aren't ordered. - # TODO(rspangler): Automatically write to disk for now; should delay until - # node-evaluation time. + # TODO(rspangler): Automatically write to disk for now; should delay until node-evaluation time. self.Write() @@ -232,16 +195,17 @@ def Write(self, writer=gyp.common.WriteOnDiff): all_entries.add(e) # If this is a folder, check its entries too. - if isinstance(e, MSVSFolder): + if isinstance(e, MSVSFolderEntry): entries_to_check += e.entries all_entries = sorted(all_entries) # Open file and print header f = writer(self.path) - f.write('Microsoft Visual Studio Solution File, ' - 'Format Version %s\r\n' % self.version.SolutionVersion()) - f.write('# %s\r\n' % self.version.Description()) + f.write( + 'Microsoft Visual Studio Solution File, Format Version %s\n' + '# %s\n' % (self.version.solution_version, self.version.description) + ) # Project entries sln_root = os.path.split(self.path)[0] @@ -250,91 +214,91 @@ def Write(self, writer=gyp.common.WriteOnDiff): # msbuild does not accept an empty folder_name. # use '.' in case relative_path is empty. folder_name = relative_path.replace('/', '\\') or '.' - f.write('Project("%s") = "%s", "%s", "%s"\r\n' % ( + f.write('Project("%s") = "%s", "%s", "%s"\n' % ( e.entry_type_guid, # Entry type GUID e.name, # Folder name folder_name, # Folder name (again) - e.get_guid(), # Entry GUID + e.guid, # Entry GUID )) # TODO(rspangler): Need a way to configure this stuff if self.websiteProperties: - f.write('\tProjectSection(WebsiteProperties) = preProject\r\n' - '\t\tDebug.AspNetCompiler.Debug = "True"\r\n' - '\t\tRelease.AspNetCompiler.Debug = "False"\r\n' - '\tEndProjectSection\r\n') + f.write('\tProjectSection(WebsiteProperties) = preProject\n' + '\t\tDebug.AspNetCompiler.Debug = "True"\n' + '\t\tRelease.AspNetCompiler.Debug = "False"\n' + '\tEndProjectSection\n') - if isinstance(e, MSVSFolder): + if isinstance(e, MSVSFolderEntry): if e.items: - f.write('\tProjectSection(SolutionItems) = preProject\r\n') - for i in e.items: - f.write('\t\t%s = %s\r\n' % (i, i)) - f.write('\tEndProjectSection\r\n') + f.write('\tProjectSection(SolutionItems) = preProject\n') + for i in sorted(e.items): + f.write('\t\t%s = %s\n' % (i, i)) + f.write('\tEndProjectSection\n') - if isinstance(e, MSVSProject): + if isinstance(e, MSVSProjectEntry): if e.dependencies: - f.write('\tProjectSection(ProjectDependencies) = postProject\r\n') - for d in e.dependencies: - f.write('\t\t%s = %s\r\n' % (d.get_guid(), d.get_guid())) - f.write('\tEndProjectSection\r\n') + f.write('\tProjectSection(ProjectDependencies) = postProject\n') + for d in sorted(e.dependencies): + f.write('\t\t%s = %s\n' % (d.guid, d.guid)) + f.write('\tEndProjectSection\n') - f.write('EndProject\r\n') + f.write('EndProject\n') # Global section - f.write('Global\r\n') + f.write('Global\n') # Configurations (variants) - f.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n') - for v in self.variants: - f.write('\t\t%s = %s\r\n' % (v, v)) - f.write('\tEndGlobalSection\r\n') + f.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n') + for v in sorted(self.variants): + f.write('\t\t%s = %s\n' % (v, v)) + f.write('\tEndGlobalSection\n') # Sort config guids for easier diffing of solution changes. config_guids = [] config_guids_overrides = {} for e in all_entries: - if isinstance(e, MSVSProject): - config_guids.append(e.get_guid()) - config_guids_overrides[e.get_guid()] = e.config_platform_overrides + if isinstance(e, MSVSProjectEntry): + config_guids.append(e.guid) + config_guids_overrides[e.guid] = e.config_platform_overrides config_guids.sort() - f.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n') + f.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n') for g in config_guids: - for v in self.variants: + for v in sorted(self.variants): nv = config_guids_overrides[g].get(v, v) # Pick which project configuration to build for this solution # configuration. - f.write('\t\t%s.%s.ActiveCfg = %s\r\n' % ( + f.write('\t\t%s.%s.ActiveCfg = %s\n' % ( g, # Project GUID v, # Solution build configuration nv, # Project build config for that solution config )) # Enable project in this solution configuration. - f.write('\t\t%s.%s.Build.0 = %s\r\n' % ( + f.write('\t\t%s.%s.Build.0 = %s\n' % ( g, # Project GUID v, # Solution build configuration nv, # Project build config for that solution config )) - f.write('\tEndGlobalSection\r\n') + f.write('\tEndGlobalSection\n') # TODO(rspangler): Should be able to configure this stuff too (though I've # never seen this be any different) - f.write('\tGlobalSection(SolutionProperties) = preSolution\r\n') - f.write('\t\tHideSolutionNode = FALSE\r\n') - f.write('\tEndGlobalSection\r\n') + f.write('\tGlobalSection(SolutionProperties) = preSolution\n') + f.write('\t\tHideSolutionNode = FALSE\n') + f.write('\tEndGlobalSection\n') # Folder mappings # 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') + if any([e.entries for e in all_entries if isinstance(e, MSVSFolderEntry)]): + f.write('\tGlobalSection(NestedProjects) = preSolution\n') for e in all_entries: - if not isinstance(e, MSVSFolder): + if not isinstance(e, MSVSFolderEntry): 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('\t\t%s = %s\n' % (subentry.guid, e.guid)) + f.write('\tEndGlobalSection\n') - f.write('EndGlobal\r\n') + f.write('EndGlobal\n') f.close() diff --git a/tools/gyp/pylib/gyp/MSVSSettings.py b/tools/gyp/gyp/MSVS/MSVSSettings.py similarity index 97% rename from tools/gyp/pylib/gyp/MSVSSettings.py rename to tools/gyp/gyp/MSVS/MSVSSettings.py index 58ce0bb1edfefd..db61bb082bf964 100644 --- a/tools/gyp/pylib/gyp/MSVSSettings.py +++ b/tools/gyp/gyp/MSVS/MSVSSettings.py @@ -14,9 +14,14 @@ MSBuild install directory, e.g. c:\Program Files (x86)\MSBuild """ +from __future__ import print_function + import sys import re +if 'basestring' not in __builtins__: + basestring = str + # Dictionaries of settings validators. The key is the tool name, the value is # a dictionary mapping setting names to validation functions. _msvs_validators = {} @@ -298,6 +303,7 @@ def _MSVSOnly(tool, name, setting_type): setting_type: the type of this setting. """ + # noinspection PyUnusedLocal def _Translate(unused_value, unused_msbuild_settings): # Since this is for MSVS only settings, no translation will happen. pass @@ -400,7 +406,7 @@ def _ValidateExclusionSetting(setting, settings, error_msg, stderr=sys.stderr): if unrecognized: # We don't know this setting. Give a warning. - print >> stderr, error_msg + print(error_msg, file=stderr) def FixVCMacroSlashes(s): @@ -417,7 +423,7 @@ def FixVCMacroSlashes(s): def ConvertVCMacrosToMSBuild(s): - """Convert the MSVS macros found in the string to the MSBuild equivalent. + """Convert the the MSVS macros found in the string to the MSBuild equivalent. This list is probably not exhaustive. Add as needed. """ @@ -433,7 +439,7 @@ def ConvertVCMacrosToMSBuild(s): '$(PlatformName)': '$(Platform)', '$(SafeInputName)': '%(Filename)', } - for old, new in replace_map.iteritems(): + for old, new in replace_map.items(): s = s.replace(old, new) s = FixVCMacroSlashes(s) return s @@ -453,17 +459,18 @@ def ConvertToMSBuildSettings(msvs_settings, stderr=sys.stderr): dictionaries of settings and their values. """ msbuild_settings = {} - for msvs_tool_name, msvs_tool_settings in msvs_settings.iteritems(): + for msvs_tool_name, msvs_tool_settings in msvs_settings.items(): if msvs_tool_name in _msvs_to_msbuild_converters: msvs_tool = _msvs_to_msbuild_converters[msvs_tool_name] - for msvs_setting, msvs_value in msvs_tool_settings.iteritems(): + for msvs_setting, msvs_value in msvs_tool_settings.items(): if msvs_setting in msvs_tool: # Invoke the translation function. try: msvs_tool[msvs_setting](msvs_value, msbuild_settings) - except ValueError, e: - print >> stderr, ('Warning: while converting %s/%s to MSBuild, ' - '%s' % (msvs_tool_name, msvs_setting, e)) + except ValueError as e: + print(('Warning: while converting %s/%s to MSBuild, ' + '%s' % (msvs_tool_name, msvs_setting, e)), + file=stderr) else: _ValidateExclusionSetting(msvs_setting, msvs_tool, @@ -472,8 +479,8 @@ def ConvertToMSBuildSettings(msvs_settings, stderr=sys.stderr): (msvs_tool_name, msvs_setting)), stderr) else: - print >> stderr, ('Warning: unrecognized tool %s while converting to ' - 'MSBuild.' % msvs_tool_name) + print(('Warning: unrecognized tool %s while converting to ' + 'MSBuild.' % msvs_tool_name), file=stderr) return msbuild_settings @@ -513,13 +520,13 @@ def _ValidateSettings(validators, settings, stderr): for tool_name in settings: if tool_name in validators: tool_validators = validators[tool_name] - for setting, value in settings[tool_name].iteritems(): + for setting, value in settings[tool_name].items(): if setting in tool_validators: try: tool_validators[setting](value) - except ValueError, e: - print >> stderr, ('Warning: for %s/%s, %s' % - (tool_name, setting, e)) + except ValueError as e: + print(('Warning: for %s/%s, %s' % + (tool_name, setting, e)), file=stderr) else: _ValidateExclusionSetting(setting, tool_validators, @@ -528,7 +535,7 @@ def _ValidateSettings(validators, settings, stderr): stderr) else: - print >> stderr, ('Warning: unrecognized tool %s' % tool_name) + print(('Warning: unrecognized tool %s' % tool_name), file=stderr) # MSVS and MBuild names of the tools. @@ -539,7 +546,7 @@ def _ValidateSettings(validators, settings, stderr): _lib = _Tool('VCLibrarianTool', 'Lib') _manifest = _Tool('VCManifestTool', 'Manifest') _masm = _Tool('MASM', 'MASM') -_armasm = _Tool('ARMASM', 'ARMASM') +_marmasm = _Tool('MARMASM', 'MARMASM') _AddTool(_compile) @@ -549,7 +556,7 @@ def _ValidateSettings(validators, settings, stderr): _AddTool(_lib) _AddTool(_manifest) _AddTool(_masm) -_AddTool(_armasm) +_AddTool(_marmasm) # Add sections only found in the MSBuild settings. _msbuild_validators[''] = {} _msbuild_validators['ProjectReference'] = {} @@ -972,7 +979,9 @@ def _ValidateSettings(validators, settings, stderr): _Enumeration(['NotSet', 'Win32', # /env win32 'Itanium', # /env ia64 - 'X64'])) # /env x64 + 'X64', # /env x64 + 'ARM64', # /env arm64 + ])) _Same(_midl, 'EnableErrorChecks', _Enumeration(['EnableCustom', 'None', # /error none diff --git a/tools/gyp/pylib/gyp/MSVSToolFile.py b/tools/gyp/gyp/MSVS/MSVSToolFile.py similarity index 82% rename from tools/gyp/pylib/gyp/MSVSToolFile.py rename to tools/gyp/gyp/MSVS/MSVSToolFile.py index 74e529a17f1dca..12cc29e81d924c 100644 --- a/tools/gyp/pylib/gyp/MSVSToolFile.py +++ b/tools/gyp/gyp/MSVS/MSVSToolFile.py @@ -4,7 +4,6 @@ """Visual Studio project reader/writer.""" -import gyp.common import gyp.easy_xml as easy_xml @@ -48,11 +47,9 @@ def AddCustomBuildRule(self, name, cmd, description, def WriteIfChanged(self): """Writes the tool file.""" - content = ['VisualStudioToolFile', - {'Version': '8.00', - 'Name': self.name - }, - self.rules_section - ] - easy_xml.WriteXmlIfChanged(content, self.tool_file_path, - encoding="Windows-1252") + content = [ + 'VisualStudioToolFile', + {'Version': '8.00', 'Name': self.name}, + self.rules_section + ] + easy_xml.WriteXmlIfChanged(content, self.tool_file_path, encoding="Windows-1252") diff --git a/tools/gyp/gyp/MSVS/MSVSVersion.py b/tools/gyp/gyp/MSVS/MSVSVersion.py new file mode 100644 index 00000000000000..79e6c3dffda58b --- /dev/null +++ b/tools/gyp/gyp/MSVS/MSVSVersion.py @@ -0,0 +1,365 @@ +# 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. + +"""Handle version information related to Visual Stdio.""" + +import os +import glob +from gyp.MSVS import TryQueryRegistryValue + +msvs_version_map = { + 'auto': ('16.0', '15.0', '14.0', '12.0', '10.0', '9.0', '8.0', '11.0'), + '2005': ('8.0',), + '2005e': ('8.0',), + '2008': ('9.0',), + '2008e': ('9.0',), + '2010': ('10.0',), + '2010e': ('10.0',), + '2012': ('11.0',), + '2012e': ('11.0',), + '2013': ('12.0',), + '2013e': ('12.0',), + '2015': ('14.0',), + '2017': ('15.0',), + '2019': ('16.0',), +} +version_to_year = { + '8.0': '2005', + '9.0': '2008', + '10.0': '2010', + '11.0': '2012', + '12.0': '2013', + '14.0': '2015', + '15.0': '2017', + '16.0': '2019', +} + +def _JoinPath(*args): + return os.path.normpath(os.path.join(*args)) + + +class VisualStudioVersion(object): + """Information regarding a version of Visual Studio.""" + + def __init__(self, + short_name, description, + solution_version, project_version, + flat_sln=False, uses_vcxproj=True, + default_toolset=None, compatible_sdks=None): + self.short_name = short_name + self.description = description + self.solution_version = solution_version + self.project_version = project_version + self.flat_sln = flat_sln + self.uses_vcxproj = uses_vcxproj + self.default_toolset = default_toolset + self.compatible_sdks = compatible_sdks + self.path = '' + self.sdk_based = False + + def ProjectExtension(self): + """Returns the file extension for the project.""" + return self.uses_vcxproj and '.vcxproj' or '.vcproj' + + def ToolPath(self, tool): + """Returns the path to a given compiler tool. """ + return os.path.normpath(os.path.join(self.path, "VC", "bin", tool)) + + def DefaultToolset(self): + """Returns the msbuild toolset version that will be used in the absence + of a user override.""" + return self.default_toolset + + def _SetupScriptInternal(self, target_arch): + """Returns a command (with arguments) to be used to set up the + environment.""" + # If WindowsSDKDir is set and SetEnv.Cmd exists then we are using the + # depot_tools build tools and should run SetEnv.Cmd to set up the + # environment. The check for WindowsSDKDir alone is not sufficient because + # this is set by running vcvarsall.bat. + sdk_dir = os.environ.get('WindowsSDKDir', '') + setup_path = _JoinPath(sdk_dir, 'Bin', 'SetEnv.Cmd') + if self.sdk_based and sdk_dir and os.path.exists(setup_path): + return [setup_path, '/' + target_arch] + + is_host_arch_x64 = ( + os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or + os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64' + ) + + # For VS2017 (and newer) it's fairly easy + if self.short_name >= '2017': + script_path = _JoinPath(self.path, 'VC', 'Auxiliary', 'Build', 'vcvarsall.bat') + + # Always use a native executable, cross-compiling if necessary. + host_arch = 'amd64' if is_host_arch_x64 else 'x86' + msvc_target_arch = 'amd64' if target_arch == 'x64' else 'x86' + arg = host_arch + if host_arch != msvc_target_arch: + arg += '_' + msvc_target_arch + + return [script_path, arg] + + # We try to find the best version of the env setup batch. + vcvarsall = _JoinPath(self.path, 'VC', 'vcvarsall.bat') + if target_arch == 'x86': + if self.short_name >= '2013' and self.short_name[-1] != 'e' and is_host_arch_x64: + # VS2013 and later, non-Express have a x64-x86 cross that we want + # to prefer. + return [vcvarsall, 'amd64_x86'] + else: + # Otherwise, the standard x86 compiler. We don't use VC/vcvarsall.bat + # for x86 because vcvarsall calls vcvars32, which it can only find if + # VS??COMNTOOLS is set, which isn't guaranteed. + return [_JoinPath(self.path, 'Common7', 'Tools', 'vsvars32.bat')] + elif target_arch == 'x64': + arg = 'x86_amd64' + # 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 is_host_arch_x64: + arg = 'amd64' + return [vcvarsall, arg] + + def SetupScript(self, target_arch): + script_data = self._SetupScriptInternal(target_arch) + script_path = script_data[0] + if not os.path.exists(script_path): + raise Exception('%s is missing - make sure VC++ tools are installed.' % script_path) + return script_data + + +MSVS_VERSIONS = { + '2019': + VisualStudioVersion( + short_name='2019', + description='Visual Studio 2019', + solution_version='12.00', + project_version='15.0', + default_toolset='v142', + compatible_sdks='8.1,10.0' + ), + '2017': + VisualStudioVersion( + short_name='2017', + description='Visual Studio 2017', + solution_version='12.00', + project_version='15.0', + default_toolset='v141', + compatible_sdks='8.1,10.0' + ), + '2015': + VisualStudioVersion( + short_name='2015', + description='Visual Studio 2015', + solution_version='12.00', + project_version='14.0', + default_toolset='v140' + ), + '2013': + VisualStudioVersion( + short_name='2013', + description='Visual Studio 2013', + solution_version='13.00', + project_version='12.0', + default_toolset='v120' + ), + '2013e': + VisualStudioVersion( + short_name='2013e', + description='Visual Studio 2013', + solution_version='13.00', + project_version='12.0', + default_toolset='v120' + ), + '2012': + VisualStudioVersion( + short_name='2012', + description='Visual Studio 2012', + solution_version='12.00', + project_version='4.0', + default_toolset='v110' + ), + '2012e': + VisualStudioVersion( + short_name='2012e', + description='Visual Studio 2012', + solution_version='12.00', + project_version='4.0', + flat_sln=True, + default_toolset='v110' + ), + '2010': + VisualStudioVersion( + short_name='2010', + description='Visual Studio 2010', + solution_version='11.00', + project_version='4.0', + ), + '2010e': + VisualStudioVersion( + short_name='2010e', + description='Visual C++ Express 2010', + solution_version='11.00', + project_version='4.0', + flat_sln=True, + ), + '2008': + VisualStudioVersion( + short_name='2008', + description='Visual Studio 2008', + solution_version='10.00', + project_version='9.00', + uses_vcxproj=False, + ), + '2008e': + VisualStudioVersion( + short_name='2008e', + description='Visual Studio 2008', + solution_version='10.00', + project_version='9.00', + flat_sln=True, + uses_vcxproj=False, + ), + '2005': + VisualStudioVersion( + short_name='2005', + description='Visual Studio 2005', + solution_version='9.00', + project_version='8.00', + flat_sln=False, + uses_vcxproj=False, + ), + '2005e': + VisualStudioVersion( + short_name='2005e', + description='Visual Studio 2005', + solution_version='9.00', + project_version='8.00', + flat_sln=True, + uses_vcxproj=False, + ), +} + +def _CreateVersion(name, path, sdk_based=False): + """ + Sets up MSVS project generation. + + Setup is based off the GYP_MSVS_VERSION environment variable or whatever is auto-detected if GYP_MSVS_VERSION + is not explicitly specified. If a version is passed in that doesn't match a value in versions python will throw a error. + """ + if path: + path = os.path.normpath(path) + version = MSVS_VERSIONS[str(name)] + version.path = path + version.sdk_based = sdk_based + return version + + +def _DetectVisualStudioVersion(wanted_version, force_express): + for version in msvs_version_map[wanted_version]: + # Old method of searching for which VS version is installed + # We don't use the 2010-encouraged-way because we also want to get the + # path to the binaries, which it doesn't offer. + keys = [ + r'Software\Microsoft\VisualStudio\%s' % version, + r'Software\Wow6432Node\Microsoft\VisualStudio\%s' % version, + r'Software\Microsoft\VCExpress\%s' % version, + r'Software\Wow6432Node\Microsoft\VCExpress\%s' % version + ] + for key in keys: + path = TryQueryRegistryValue(key, 'InstallDir') + if not path: + continue + # Check for full. + full_path = os.path.join(path, 'devenv.exe') + express_path = os.path.join(path, '*express.exe') + vc_root_path = os.path.join(path, '..', '..') + if not force_express and os.path.exists(full_path): + # Add this one. + return _CreateVersion(version_to_year[version], vc_root_path) + # Check for express. + elif glob.glob(express_path): + # Add this one. + return _CreateVersion(version_to_year[version] + 'e', vc_root_path) + + # The old method above does not work when only SDK is installed. + keys2 = [ + r'Software\Microsoft\VisualStudio\SxS\VC7', + r'Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7', + r'Software\Microsoft\VisualStudio\SxS\VS7', + r'Software\Wow6432Node\Microsoft\VisualStudio\SxS\VS7' + ] + for key in keys2: + path = TryQueryRegistryValue(key, version) + if not path: + continue + if version == '15.0': + if os.path.exists(path): + return _CreateVersion('2017', path) + elif version == '16.0': + if os.path.exists(path): + return _CreateVersion('2019', path) + elif version != '14.0': # There is no Express edition for 2015. + return _CreateVersion(version_to_year[version] + 'e', os.path.join(path, '..'), sdk_based=True) + + return None + + +def SelectVisualStudioVersion(wanted_version='auto'): + """Select which version of Visual Studio projects to generate. + + Arguments: + wanted_version: Hook to allow caller to force a particular version (vs auto). + Returns: + An object representing a visual studio project format version. + """ + wanted_version = str(wanted_version) + + override_path = os.environ.get('GYP_MSVS_OVERRIDE_PATH') + gyp_env_version = os.environ.get('GYP_MSVS_VERSION', wanted_version) + if override_path: + if gyp_env_version == 'auto': + raise ValueError('GYP_MSVS_OVERRIDE_PATH requires GYP_MSVS_VERSION to be set to a particular version.') + return _CreateVersion(gyp_env_version, override_path, sdk_based=True) + + # In auto mode, check environment variable for override. + if wanted_version == 'auto': + wanted_version = version_to_year.get(os.environ.get('VisualStudioVersion'), gyp_env_version) + version = _DetectVisualStudioVersion(wanted_version, 'e' in wanted_version) + if version: + return version + if wanted_version != 'auto': + # Even if we did not actually detect a version, we fake it + return _CreateVersion(wanted_version, None) + raise ValueError('Could not locate Visual Studio installation.') + + +def WindowsTargetPlatformVersion(possible_sdk_versions): + # If the environment is set, ignore the possible version hint + env_sdk_version = os.environ.get('WindowsSDKVersion', '') + if env_sdk_version: + return env_sdk_version.replace('\\', '') + + if not possible_sdk_versions: + return None + + versions_args = possible_sdk_versions.split(',') + key_template = r'Software\%sMicrosoft\Microsoft SDKs\Windows\%s' + keys = [(key_template % (sub, ver)) for ver in versions_args for sub in ['', 'Wow6432Node\\',]] + for key in keys: + sdk_dir = TryQueryRegistryValue(key, 'InstallationFolder') + if not sdk_dir: + continue + # Find a matching entry in sdk_dir\include. + product_version = TryQueryRegistryValue(key, 'ProductVersion') + sdk_include_dir = os.path.join(sdk_dir, 'include') + if not os.path.isdir(sdk_include_dir): + continue + names = sorted(x for x in os.listdir(sdk_include_dir) if x.startswith(product_version)) + if names: + return names[-1] + + return None + + diff --git a/tools/gyp/gyp/MSVS/__init__.py b/tools/gyp/gyp/MSVS/__init__.py new file mode 100644 index 00000000000000..5dce120835569e --- /dev/null +++ b/tools/gyp/gyp/MSVS/__init__.py @@ -0,0 +1,507 @@ +from __future__ import print_function + +import copy +import json +import os +import subprocess +import sys +import traceback + +from gyp.common import memoize + +try: + WindowsError +except NameError: + # noinspection PyShadowingBuiltins + WindowsError = OSError + +try: + import winreg +except ImportError: + try: + import _winreg as winreg + except ImportError: + # Just a mock class to silence static analysers. + class winreg(object): + HKEY_LOCAL_MACHINE = '' + @staticmethod + def OpenKey(root, key): + raise NotImplementedError() + @staticmethod + def QueryValueEx(key, value): + raise NotImplementedError() + +class Tool(object): + """Visual Studio tool.""" + + def __init__(self, name, attrs=None): + """Initializes the tool. + + Args: + name: Tool name. + attrs: Dict of tool attributes; may be None. + """ + self._attrs = attrs or {} + self._attrs['Name'] = name + + def _GetSpecification(self): + """Creates an element for the tool. + + Returns: + A new xml.dom.Element for the tool. + """ + return ['Tool', self._attrs] + + +class Filter(object): + """Visual Studio filter - that is, a virtual folder.""" + + def __init__(self, name, contents=None): + """Initializes the folder. + + Args: + name: Filter (folder) name. + contents: List of filenames and/or Filter objects contained. + """ + self.name = name + self.contents = list(contents or []) + + +# A dictionary mapping supported target types to extensions. +TARGET_TYPE_EXT = { + 'executable': 'exe', + 'loadable_module': 'dll', + 'shared_library': 'dll', + 'static_library': 'lib', + 'windows_driver': 'sys', +} + + +def _GetLargePdbShimCcPath(): + """Returns the path of the large_pdb_shim.cc file.""" + this_dir = os.path.dirname(__file__) + lib_dir = os.path.join(this_dir, '..') + large_pdb_shim_cc_rel = os.path.join(lib_dir, 'buildtime_helpers', 'large-pdb-shim.cc') + large_pdb_shim_cc = os.path.abspath(large_pdb_shim_cc_rel) + return large_pdb_shim_cc + + +def _DeepCopySomeKeys(in_dict, keys): + """Performs a partial deep-copy on |in_dict|, only copying the keys in |keys|. + + Arguments: + in_dict: The dictionary to copy. + keys: The keys to be copied. If a key is in this list and doesn't exist in + |in_dict| this is not an error. + Returns: + The partially deep-copied dictionary. + """ + d = {} + for key in keys: + if key not in in_dict: + continue + d[key] = copy.deepcopy(in_dict[key]) + return d + + +def _SuffixName(name, suffix): + """Add a suffix to the end of a target. + + Arguments: + name: name of the target (foo#target) + suffix: the suffix to be added + Returns: + Target name with suffix added (foo_suffix#target) + """ + parts = name.rsplit('#', 1) + parts[0] = '%s_%s' % (parts[0], suffix) + return '#'.join(parts) + + +def _ShardName(name, number): + """Add a shard number to the end of a target. + + Arguments: + name: name of the target (foo#target) + number: shard number + Returns: + Target name with shard added (foo_1#target) + """ + return _SuffixName(name, str(number)) + + +def ShardTargets(target_list, target_dicts): + """Shard some targets apart to work around the linkers limits. + + Arguments: + target_list: List of target pairs: 'base/base.gyp:base'. + target_dicts: Dict of target properties keyed on target pair. + Returns: + Tuple of the new sharded versions of the inputs. + """ + # Gather the targets to shard, and how many pieces. + targets_to_shard = {} + for t in target_dicts: + shards = int(target_dicts[t].get('msvs_shard', 0)) + if shards: + targets_to_shard[t] = shards + # Shard target_list. + new_target_list = [] + for t in target_list: + if t in targets_to_shard: + for i in range(targets_to_shard[t]): + new_target_list.append(_ShardName(t, i)) + else: + new_target_list.append(t) + # Shard target_dict. + new_target_dicts = {} + for t in target_dicts: + if t in targets_to_shard: + for i in range(targets_to_shard[t]): + name = _ShardName(t, i) + new_target_dicts[name] = copy.copy(target_dicts[t]) + new_target_dicts[name]['target_name'] = _ShardName( + new_target_dicts[name]['target_name'], i) + sources = new_target_dicts[name].get('sources', []) + new_sources = [] + for pos in range(i, len(sources), targets_to_shard[t]): + new_sources.append(sources[pos]) + new_target_dicts[name]['sources'] = new_sources + else: + new_target_dicts[t] = target_dicts[t] + # Shard dependencies. + for t in sorted(new_target_dicts): + for dep_type in ('dependencies', 'dependencies_original'): + dependencies = copy.copy(new_target_dicts[t].get(dep_type, [])) + 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][dep_type] = new_dependencies + + return new_target_list, new_target_dicts + + +def _GetPdbPath(target_dict, config_name, gyp_vars): + """Returns the path to the PDB file that will be generated by a given + configuration. + + The lookup proceeds as follows: + - Look for an explicit path in the VCLinkerTool configuration block. + - Look for an 'msvs_large_pdb_path' variable. + - Use '<(PRODUCT_DIR)/<(product_name).(exe|dll).pdb' if 'product_name' is + specified. + - Use '<(PRODUCT_DIR)/<(target_name).(exe|dll).pdb'. + + Arguments: + target_dict: The target dictionary to be searched. + config_name: The name of the configuration of interest. + gyp_vars: A dictionary of common GYP variables with generator-specific values. + Returns: + The path of the corresponding PDB file. + """ + config = target_dict['configurations'][config_name] + msvs = config.setdefault('msvs_settings', {}) + + linker = msvs.get('VCLinkerTool', {}) + + pdb_path = linker.get('ProgramDatabaseFile') + if pdb_path: + return pdb_path + + variables = target_dict.get('variables', {}) + pdb_path = variables.get('msvs_large_pdb_path', None) + if pdb_path: + return pdb_path + + + 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_path = gyp_vars['PRODUCT_DIR'] + '/' + pdb_base + + return pdb_path + + +def InsertLargePdbShims(target_list, target_dicts, gyp_vars): + """Insert a shim target that forces the linker to use 4KB pagesize PDBs. + + This is a workaround for targets with PDBs greater than 1GB in size, the + limit for the 1KB pagesize PDBs created by the linker by default. + + Arguments: + target_list: List of target pairs: 'base/base.gyp:base'. + target_dicts: Dict of target properties keyed on target pair. + gyp_vars: A dictionary of common GYP variables with generator-specific values. + Returns: + Tuple of the shimmed version of the inputs. + """ + # Determine which targets need shimming. + targets_to_shim = [] + for t in target_dicts: + target_dict = target_dicts[t] + + # We only want to shim targets that have msvs_large_pdb enabled. + if not int(target_dict.get('msvs_large_pdb', 0)): + continue + # This is intended for executable, shared_library and loadable_module + # targets where every configuration is set up to produce a PDB output. + # If any of these conditions is not true then the shim logic will fail + # below. + targets_to_shim.append(t) + + large_pdb_shim_cc = _GetLargePdbShimCcPath() + + for t in targets_to_shim: + target_dict = target_dicts[t] + target_name = target_dict.get('target_name') + + base_dict = _DeepCopySomeKeys(target_dict, + ['configurations', 'default_configuration', 'toolset']) + + # This is the dict for copying the source file (part of the GYP tree) + # to the intermediate directory of the project. This is necessary because + # we can't always build a relative path to the shim source file (on Windows + # GYP and the project may be on different drives), and Ninja hates absolute + # paths (it ends up generating the .obj and .obj.d alongside the source + # file, polluting GYPs tree). + copy_suffix = 'large_pdb_copy' + copy_target_name = target_name + '_' + copy_suffix + full_copy_target_name = _SuffixName(t, copy_suffix) + shim_cc_basename = os.path.basename(large_pdb_shim_cc) + shim_cc_dir = gyp_vars['SHARED_INTERMEDIATE_DIR'] + '/' + copy_target_name + shim_cc_path = shim_cc_dir + '/' + shim_cc_basename + copy_dict = copy.deepcopy(base_dict) + copy_dict['target_name'] = copy_target_name + copy_dict['type'] = 'none' + copy_dict['sources'] = [ large_pdb_shim_cc ] + copy_dict['copies'] = [{ + 'destination': shim_cc_dir, + 'files': [ large_pdb_shim_cc ] + }] + + # This is the dict for the PDB generating shim target. It depends on the + # copy target. + shim_suffix = 'large_pdb_shim' + shim_target_name = target_name + '_' + shim_suffix + full_shim_target_name = _SuffixName(t, shim_suffix) + shim_dict = copy.deepcopy(base_dict) + shim_dict['target_name'] = shim_target_name + shim_dict['type'] = 'static_library' + shim_dict['sources'] = [ shim_cc_path ] + shim_dict['dependencies'] = [ full_copy_target_name ] + + # Set up the shim to output its PDB to the same location as the final linker + # target. + for config_name, config in shim_dict.get('configurations').items(): + pdb_path = _GetPdbPath(target_dict, config_name, gyp_vars) + + # A few keys that we don't want to propagate. + for key in ['msvs_precompiled_header', 'msvs_precompiled_source', 'test']: + config.pop(key, None) + + msvs = config.setdefault('msvs_settings', {}) + + # Update the compiler directives in the shim target. + compiler = msvs.setdefault('VCCLCompilerTool', {}) + compiler['DebugInformationFormat'] = '3' + compiler['ProgramDataBaseFileName'] = pdb_path + + # Set the explicit PDB path in the appropriate configuration of the + # original target. + config = target_dict['configurations'][config_name] + msvs = config.setdefault('msvs_settings', {}) + linker = msvs.setdefault('VCLinkerTool', {}) + linker['GenerateDebugInformation'] = 'true' + linker['ProgramDatabaseFile'] = pdb_path + + # Add the new targets. They must go to the beginning of the list so that + # the dependency generation works as expected in ninja. + target_list.insert(0, full_copy_target_name) + target_list.insert(0, full_shim_target_name) + target_dicts[full_copy_target_name] = copy_dict + target_dicts[full_shim_target_name] = shim_dict + + # Update the original target to depend on the shim target. + target_dict.setdefault('dependencies', []).append(full_shim_target_name) + + return target_list, target_dicts + + +def TryQueryRegistryValue(key, value=None, root=winreg.HKEY_LOCAL_MACHINE): + try: + with winreg.OpenKey(root, key) as kh: + value, value_type = winreg.QueryValueEx(kh, value) + return value + except WindowsError: + return None + except NotImplementedError: + return None + + +def FindVisualStudioInstallation(): + """ + Returns appropriate values for .build_tool and .uses_msbuild fields + of TestGypBase for Visual Studio. + + We use the value specified by GYP_MSVS_VERSION. If not specified, we + search for likely deployment paths. + """ + msvs_version = 'auto' + for flag in (f for f in sys.argv if f.startswith('msvs_version=')): + msvs_version = flag.split('=')[-1] + msvs_version = os.environ.get('GYP_MSVS_VERSION', msvs_version) + + override_build_tool = os.environ.get('GYP_BUILD_TOOL') + if override_build_tool: + return override_build_tool, True, override_build_tool, msvs_version + + if msvs_version == 'auto' or msvs_version >= '2017': + msbuild_exes = [] + top_vs_info = VSSetup_PowerShell() + if top_vs_info: + inst_path = top_vs_info['InstallationPath'] + args2 = ['cmd.exe', '/d', '/c', + 'cd', '/d', inst_path, + '&', 'dir', '/b', '/s', 'msbuild.exe'] + msbuild_exes = subprocess.check_output(args2).strip().splitlines() + if len(msbuild_exes): + msbuild_path = str(msbuild_exes[0].decode('utf-8')) + os.environ['GYP_MSVS_VERSION'] = top_vs_info['CatalogVersion'] + os.environ['GYP_BUILD_TOOL'] = msbuild_path + return msbuild_path, True, msbuild_path, msvs_version + + possible_roots = ['%s:\\Program Files%s' % (chr(drive), suffix) + for drive in range(ord('C'), ord('Z') + 1) + for suffix in ['', ' (x86)']] + possible_paths = { + '2015': r'Microsoft Visual Studio 14.0\Common7\IDE\devenv.com', + '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', + '2005': r'Microsoft Visual Studio 8\Common7\IDE\devenv.com' + } + + # Check that the path to the specified GYP_MSVS_VERSION exists. + if msvs_version in possible_paths: + path = possible_paths[msvs_version] + for r in possible_roots: + build_tool = os.path.join(r, path) + if os.path.exists(build_tool): + uses_msbuild = msvs_version >= '2010' + msbuild_path = FindMSBuildInstallation(msvs_version) + return build_tool, uses_msbuild, msbuild_path, msvs_version + else: + print('Warning: Environment variable GYP_MSVS_VERSION specifies "%s" ' + 'but corresponding "%s" was not found.' % (msvs_version, path)) + print('Error: could not find MSVS version %s' % msvs_version) + sys.exit(1) + + +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. + """ + + msvs_to_msbuild = { + '2015': '14.0', + '2013': '12.0', + '2012': '4.0', # Really v4.0.30319 which comes with .NET 4.5. + '2010': '4.0' + } + + msbuild_base_key = r'SOFTWARE\Microsoft\MSBuild\ToolsVersions' + if not TryQueryRegistryValue(msbuild_base_key): + print('Error: could not find MSBuild base registry entry') + return None + + msbuild_key = '' + found_msbuild_ver = '' + if msvs_version in msvs_to_msbuild: + msbuild_test_version = msvs_to_msbuild[msvs_version] + msbuild_key = msbuild_base_key + '\\' + msbuild_test_version + if TryQueryRegistryValue(msbuild_key): + found_msbuild_ver = msbuild_test_version + else: + print('Warning: Environment variable GYP_MSVS_VERSION specifies "%s" but corresponding MSBuild "%s" was not found.' % (msvs_version, found_msbuild_ver)) + if not found_msbuild_ver: + for msvs_version in sorted(msvs_to_msbuild.keys(), reverse=True): + msbuild_test_version = msvs_to_msbuild[msvs_version] + msbuild_key = msbuild_base_key + '\\' + msbuild_test_version + if TryQueryRegistryValue(msbuild_key): + found_msbuild_ver = msbuild_test_version + break + if not found_msbuild_ver: + print('Error: could not find am MSBuild registry entry') + return None + + msbuild_path = TryQueryRegistryValue(msbuild_key, 'MSBuildToolsPath') + if not msbuild_path: + print('Error: could not get MSBuildToolsPath registry entry value for MSBuild version %s' % found_msbuild_ver) + return None + + return os.path.join(msbuild_path, 'MSBuild.exe') + + +@memoize +def VSWhere(component=None): + args1 = [ + r'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe', + '-all', '-latest', '-sort', '-format', 'json', + ] + if not component: + args1.append('-legacy') + + try: + vswhere_json = subprocess.check_output(args1) + vswhere_infos = json.loads(vswhere_json) + if len(vswhere_infos) == 0: + raise IOError("vswhere did not find any MSVS instances.") + return vswhere_infos[0] + except subprocess.CalledProcessError as e: + traceback.print_exc(file=sys.stderr) + print(e, file=sys.stderr) + return None + + +new_vs_map = { + 16: '2019', + 15: '2017', + 14: '2015', +} + + +@memoize +def VSSetup_PowerShell(): + powershell = os.path.join(os.environ['SystemRoot'], 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe') + query_script_path = os.path.join(os.path.dirname(__file__), '..', '..', 'tools', 'vssetup.powershell', 'VSQuery.ps1') + args = [ + powershell, '-ExecutionPolicy', 'Unrestricted', '-NoProfile', + query_script_path + ] + try: + vs_query_json = subprocess.check_output(args) + except subprocess.CalledProcessError as e: + print(e, file=sys.stderr) + print(e.stderr, file=sys.stderr) + raise e + try: + vs_query_infos = json.loads(vs_query_json) + except json.decoder.JSONDecodeError as e: + print(e, file=sys.stderr) + print(vs_query_json, file=sys.stderr) + raise e + assert vs_query_infos + if isinstance(vs_query_infos, dict): + vs_query_infos = [vs_query_infos] + if len(vs_query_infos) == 0: + raise IOError("vssetup.powershell did not find any MSVS instances.") + for ver in vs_query_infos: + ver['CatalogVersion'] = new_vs_map[ver['InstallationVersion']['Major']] + return vs_query_infos[0] + diff --git a/tools/gyp/gyp/Makefile.tmpl b/tools/gyp/gyp/Makefile.tmpl new file mode 100644 index 00000000000000..938948ebaf44e9 --- /dev/null +++ b/tools/gyp/gyp/Makefile.tmpl @@ -0,0 +1,223 @@ +# We borrow heavily from the kernel build setup, though we are simpler since +# we don't have Kconfig tweaking settings on us. + +# The implicit make rules have it looking for RCS files, among other things. +# We instead explicitly write all the rules we care about. +# It's even quicker (saves ~200ms) to pass -r on the command line. +MAKEFLAGS=-r + +# The source directory tree. +srcdir := %(srcdir)s +abs_srcdir := $(abspath $(srcdir)) + +# The name of the builddir. +builddir_name ?= %(builddir)s + +# The V=1 flag on command line makes us verbosely print command lines. +ifdef V + quiet= +else + quiet=quiet_ +endif + +# Specify BUILDTYPE=Release on the command line for a release build. +BUILDTYPE ?= %(default_configuration)s + +# Directory all our build output goes into. +# Note that this must be two directories beneath src/ for unit tests to pass, +# as they reach into the src/ directory for data with relative paths. +builddir ?= $(builddir_name)/$(BUILDTYPE) +abs_builddir := $(abspath $(builddir)) +depsdir := $(builddir)/.deps + +# Object output directory. +obj := $(builddir)/obj +abs_obj := $(abspath $(obj)) + +# We build up a list of every single one of the targets so we can slurp in the +# generated dependency rule Makefiles in one pass. +all_deps := + +%(make_global_settings)s + +CC.target ?= %(CC.target)s +CFLAGS.target ?= $(CPPFLAGS) $(CFLAGS) +CXX.target ?= %(CXX.target)s +CXXFLAGS.target ?= $(CPPFLAGS) $(CXXFLAGS) +LINK.target ?= %(LINK.target)s +LDFLAGS.target ?= $(LDFLAGS) +AR.target ?= $(AR) + +# C++ apps need to be linked with g++. +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. +CC.host ?= %(CC.host)s +CFLAGS.host ?= $(CPPFLAGS_host) $(CFLAGS_host) +CXX.host ?= %(CXX.host)s +CXXFLAGS.host ?= $(CPPFLAGS_host) $(CXXFLAGS_host) +LINK.host ?= %(LINK.host)s +LDFLAGS.host ?= $(LDFLAGS_host) +AR.host ?= %(AR.host)s + +# Define a dir function that can handle spaces. +# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions +# "leading spaces cannot appear in the text of the first argument as written. +# These characters can be put into the argument value by variable substitution." +empty := +space := $(empty) $(empty) + +# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces +replace_spaces = $(subst $(space),{SPACE_REPLACEMENT},$1) +unreplace_spaces = $(subst {SPACE_REPLACEMENT},$(space),$1) +dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1))) + +# Flags to make gcc output dependency info. Note that you need to be +# careful here to use the flags that ccache and distcc can understand. +# We write to a dep file on the side first and then rename at the end +# so we can't end up with a broken dep file. +depfile = $(depsdir)/$(call replace_spaces,$@).d +DEPFLAGS = %(makedep_args)s -MF $(depfile).raw + +# We have to fixup the deps output in a few ways. +# (1) the file output should mention the proper .o file. +# ccache or distcc lose the path to the target, so we convert a rule of +# the form: +# foobar.o: DEP1 DEP2 +# into +# path/to/foobar.o: DEP1 DEP2 +# (2) we want missing files not to cause us to fail to build. +# We want to rewrite +# foobar.o: DEP1 DEP2 \ +# DEP3 +# to +# DEP1: +# DEP2: +# DEP3: +# so if the files are missing, they're just considered phony rules. +# We have to do some pretty insane escaping to get those backslashes +# and dollar signs past make, the shell, and sed at the same time. +# Doesn't work with spaces, but that's fine: .d files have spaces in +# their names replaced with other characters. +define fixup_dep +# The depfile may not exist if the input file didn't have any #includes. +touch $(depfile).raw +# Fixup path as in (1). +sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile) +# Add extra rules as in (2). +# We remove slashes and replace spaces with new lines; +# remove blank lines; +# delete the first line and append a colon to the remaining lines. +sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ + grep -v '^$$' |\ + sed -e 1d -e 's|$$|:|' \ + >> $(depfile) +rm $(depfile).raw +endef +# Command definitions: +# - cmd_foo is the actual command to run; +# - quiet_cmd_foo is the brief-output summary of the command. + +quiet_cmd_cc = CC($(TOOLSET)) $@ +cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_cxx = CXX($(TOOLSET)) $@ +cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< +%(extra_commands)s +quiet_cmd_touch = TOUCH $@ +cmd_touch = touch $@ + +quiet_cmd_copy = COPY $@ +# send stderr to /dev/null to ignore messages when linking directories. +cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp %(copy_archive_args)s "$<" "$@") + +%(link_commands)s +# Define an escape_quotes function to escape single quotes. +# This allows us to handle quotes properly as long as we always use +# use single quotes and escape_quotes. +escape_quotes = $(subst ','\'',$(1)) +# This comment is here just to include a ' to unconfuse syntax highlighting. +# Define an escape_vars function to escape '$' variable syntax. +# This allows us to read/write command lines with shell variables (e.g. +# $LD_LIBRARY_PATH), without triggering make substitution. +escape_vars = $(subst $$,$$$$,$(1)) +# Helper that expands to a shell command to echo a string exactly as it is in +# make. This uses printf instead of echo because printf's behaviour with respect +# to escape sequences is more portable than echo's across different shells +# (e.g., dash, bash). +exact_echo = printf '%%s\n' '$(call escape_quotes,$(1))' +# Helper to compare the command we're about to run against the command +# we logged the last time we ran the command. Produces an empty +# string (false) when the commands match. +# Tricky point: Make has no string-equality test function. +# The kernel uses the following, but it seems like it would have false +# positives, where one string reordered its arguments. +# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ +# $(filter-out $(cmd_$@), $(cmd_$(1)))) +# We instead substitute each for the empty string into the other, and +# say they're equal if both substitutions produce the empty string. +# .d files contain {SPACE_REPLACEMENT} instead of spaces, take that into account. +command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))), $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) + +# Helper that is non-empty when a prerequisite changes. +# Normally make does this implicitly, but we force rules to always run +# so we can check their command lines. +# $? -- new prerequisites +# $| -- order-only dependencies +prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) + +# Helper that executes all postbuilds until one fails. +define do_postbuilds + @E=0;\ + for p in $(POSTBUILDS); do\ + eval $$p;\ + E=$$?;\ + if [ $$E -ne 0 ]; then\ + break;\ + fi;\ + done;\ + if [ $$E -ne 0 ]; then\ + rm -rf "$@";\ + exit $$E;\ + fi +endef + +# do_cmd: run a command via the above cmd_foo names, if necessary. +# Should always run for a given target to handle command-line changes. +# Second argument, if non-zero, makes it do asm/C/C++ dependency munging. +# Third argument, if non-zero, makes it do POSTBUILDS processing. +# Note: We intentionally do NOT call dirx for depfile, since it contains {SPACE_REPLACEMENT} for +# spaces already and dirx strips the {SPACE_REPLACEMENT} characters. +define do_cmd +$(if $(or $(command_changed),$(prereq_changed)), + @$(call exact_echo, $($(quiet)cmd_$(1))) + @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" + $(if $(findstring flock,$(word %(flock_index)d,$(cmd_$1))), + @$(cmd_$(1)) + @echo " $(quiet_cmd_$(1)): Finished", + @$(cmd_$(1)) + ) + @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) + @$(if $(2),$(fixup_dep)) + $(if $(and $(3), $(POSTBUILDS)), + $(call do_postbuilds) + ) +) +endef + +# Declare the "%(default_target)s" target first so it is the default, +# even though we don't have the deps yet. +.PHONY: %(default_target)s +%(default_target)s: + +# make looks for ways to re-generate included makefiles, but in our case, we +# don't have a direct way. Explicitly telling make that it has nothing to do +# for them makes it go faster. +%%.d: ; + +# Use FORCE_DO_CMD to force a target to run. Should be coupled with +# do_cmd. +.PHONY: FORCE_DO_CMD +FORCE_DO_CMD: + diff --git a/tools/gyp/pylib/gyp/generator/make.py b/tools/gyp/gyp/MakefileWriter.py similarity index 51% rename from tools/gyp/pylib/gyp/generator/make.py rename to tools/gyp/gyp/MakefileWriter.py index e98d93ab233ff8..7ddb7b0377a03d 100644 --- a/tools/gyp/pylib/gyp/generator/make.py +++ b/tools/gyp/gyp/MakefileWriter.py @@ -1,127 +1,11 @@ -# 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. - -# Notes: -# -# This is all roughly based on the Makefile system used by the Linux -# kernel, but is a non-recursive make -- we put the entire dependency -# graph in front of make and let it figure it out. -# -# The code below generates a separate .mk file for each target, but -# all are sourced by the top-level Makefile. This means that all -# variables in .mk-files clobber one another. Be careful to use := -# where appropriate for immediate evaluation, and similarly to watch -# that you're not relying on a variable value to last beween different -# .mk files. -# -# TODOs: -# -# Global settings and utility functions are currently stuffed in the -# toplevel Makefile. It may make sense to generate some .mk files on -# the side to keep the files readable. - +import hashlib import os import re -import sys -import subprocess -import gyp -import gyp.common -import gyp.xcode_emulation -from gyp.common import GetEnvironFallback -from gyp.common import GypError - -import hashlib - -generator_default_variables = { - 'EXECUTABLE_PREFIX': '', - 'EXECUTABLE_SUFFIX': '', - 'STATIC_LIB_PREFIX': 'lib', - 'SHARED_LIB_PREFIX': 'lib', - 'STATIC_LIB_SUFFIX': '.a', - 'INTERMEDIATE_DIR': '$(obj).$(TOOLSET)/$(TARGET)/geni', - 'SHARED_INTERMEDIATE_DIR': '$(obj)/gen', - 'PRODUCT_DIR': '$(builddir)', - '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': '$(abspath $<)', - 'RULE_INPUT_EXT': '$(suffix $<)', - 'RULE_INPUT_NAME': '$(notdir $<)', - 'CONFIGURATION_NAME': '$(BUILDTYPE)', -} - -# Make supports multiple toolsets -generator_supports_multiple_toolsets = True - -# Request sorted dependencies in the order from dependents to dependencies. -generator_wants_sorted_dependencies = False - -# Placates pylint. -generator_additional_non_configuration_keys = [] -generator_additional_path_sections = [] -generator_extra_sources_for_rules = [] -generator_filelist_paths = None - - -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') - default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib') - default_variables.setdefault('SHARED_LIB_DIR', - generator_default_variables['PRODUCT_DIR']) - default_variables.setdefault('LIB_DIR', - generator_default_variables['PRODUCT_DIR']) - - # Copy additional generator configuration data from Xcode, which is shared - # by the Mac Make generator. - import gyp.generator.xcode as xcode_generator - global generator_additional_non_configuration_keys - generator_additional_non_configuration_keys = getattr(xcode_generator, - 'generator_additional_non_configuration_keys', []) - global generator_additional_path_sections - generator_additional_path_sections = getattr(xcode_generator, - 'generator_additional_path_sections', []) - global generator_extra_sources_for_rules - generator_extra_sources_for_rules = getattr(xcode_generator, - 'generator_extra_sources_for_rules', []) - COMPILABLE_EXTENSIONS.update({'.m': 'objc', '.mm' : 'objcxx'}) - else: - operating_system = flavor - if flavor == 'android': - operating_system = 'linux' # Keep this legacy behavior for now. - default_variables.setdefault('OS', operating_system) - if flavor == 'aix': - default_variables.setdefault('SHARED_LIB_SUFFIX', '.a') - else: - default_variables.setdefault('SHARED_LIB_SUFFIX', '.so') - default_variables.setdefault('SHARED_LIB_DIR','$(builddir)/lib.$(TOOLSET)') - default_variables.setdefault('LIB_DIR', '$(obj).$(TOOLSET)') - - -def CalculateGeneratorInputInfo(params): - """Calculate the generator specific info that gets fed to input (called by - gyp).""" - generator_flags = params.get('generator_flags', {}) - android_ndk_version = generator_flags.get('android_ndk_version', None) - # Android NDK requires a strict link order. - if android_ndk_version: - 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')) - - global generator_filelist_paths - generator_filelist_paths = { - 'toplevel': params['options'].toplevel_dir, - 'qualified_out_dir': qualified_out_dir, - } +import gyp +from gyp import xcode_emulation +from gyp.common import GypError, EnsureDirExists +from gyp.generator.make import generator_default_variables,CalculateVariables # The .d checking code below uses these functions: # wildcard, sort, foreach, shell, wordlist @@ -135,372 +19,37 @@ def CalculateGeneratorInputInfo(params): # This is the replacement character. SPACE_REPLACEMENT = '?' - -LINK_COMMANDS_LINUX = """\ -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)) crsT $@ $(filter %.o,$^) - -# Due to circular dependencies between libraries :(, we wrap the -# special "figure out circular dependencies" flags around the entire -# input list during linking. -quiet_cmd_link = LINK($(TOOLSET)) $@ -cmd_link = $(LINK.$(TOOLSET)) -o $@ $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,--start-group $(LD_INPUTS) $(LIBS) -Wl,--end-group - -# We support two kinds of shared objects (.so): -# 1) shared_library, which is just bundling together many dependent libraries -# into a link line. -# 2) loadable_module, which is generating a module intended for dlopen(). -# -# They differ only slightly: -# In the former case, we want to package all dependent code into the .so. -# In the latter case, we want to package just the API exposed by the -# outermost module. -# This means shared_library uses --whole-archive, while loadable_module doesn't. -# (Note that --whole-archive is incompatible with the --start-group used in -# normal linking.) - -# Other shared-object link notes: -# - Set SONAME to the library filename so our binaries don't reference -# the local, absolute paths used on the link command-line. -quiet_cmd_solink = SOLINK($(TOOLSET)) $@ -cmd_solink = $(LINK.$(TOOLSET)) -o $@ -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) - -quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ -cmd_solink_module = $(LINK.$(TOOLSET)) -o $@ -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) -""" - -LINK_COMMANDS_MAC = """\ -quiet_cmd_alink = LIBTOOL-STATIC $@ -cmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool $(GYP_LIBTOOLFLAGS) -static -o $@ $(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)) -bundle $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) -""" - -LINK_COMMANDS_ANDROID = """\ -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)) crsT $@ $(filter %.o,$^) - -# Due to circular dependencies between libraries :(, we wrap the -# special "figure out circular dependencies" flags around the entire -# input list during linking. -quiet_cmd_link = LINK($(TOOLSET)) $@ -quiet_cmd_link_host = LINK($(TOOLSET)) $@ -cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS) -cmd_link_host = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) - -# Other shared-object link notes: -# - Set SONAME to the library filename so our binaries don't reference -# the local, absolute paths used on the link command-line. -quiet_cmd_solink = SOLINK($(TOOLSET)) $@ -cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) - -quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ -cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) -quiet_cmd_solink_module_host = SOLINK_MODULE($(TOOLSET)) $@ -cmd_solink_module_host = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) -""" - - -LINK_COMMANDS_AIX = """\ -quiet_cmd_alink = AR($(TOOLSET)) $@ -cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) -X32_64 crs $@ $(filter %.o,$^) - -quiet_cmd_alink_thin = AR($(TOOLSET)) $@ -cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) -X32_64 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 = ("""\ -# We borrow heavily from the kernel build setup, though we are simpler since -# we don't have Kconfig tweaking settings on us. - -# The implicit make rules have it looking for RCS files, among other things. -# We instead explicitly write all the rules we care about. -# It's even quicker (saves ~200ms) to pass -r on the command line. -MAKEFLAGS=-r - -# The source directory tree. -srcdir := %(srcdir)s -abs_srcdir := $(abspath $(srcdir)) - -# The name of the builddir. -builddir_name ?= %(builddir)s - -# The V=1 flag on command line makes us verbosely print command lines. -ifdef V - quiet= -else - quiet=quiet_ -endif - -# Specify BUILDTYPE=Release on the command line for a release build. -BUILDTYPE ?= %(default_configuration)s - -# Directory all our build output goes into. -# Note that this must be two directories beneath src/ for unit tests to pass, -# as they reach into the src/ directory for data with relative paths. -builddir ?= $(builddir_name)/$(BUILDTYPE) -abs_builddir := $(abspath $(builddir)) -depsdir := $(builddir)/.deps - -# Object output directory. -obj := $(builddir)/obj -abs_obj := $(abspath $(obj)) - -# We build up a list of every single one of the targets so we can slurp in the -# generated dependency rule Makefiles in one pass. -all_deps := - -%(make_global_settings)s - -CC.target ?= %(CC.target)s -CFLAGS.target ?= $(CPPFLAGS) $(CFLAGS) -CXX.target ?= %(CXX.target)s -CXXFLAGS.target ?= $(CPPFLAGS) $(CXXFLAGS) -LINK.target ?= %(LINK.target)s -LDFLAGS.target ?= $(LDFLAGS) -AR.target ?= $(AR) - -# C++ apps need to be linked with g++. -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. -CC.host ?= %(CC.host)s -CFLAGS.host ?= $(CPPFLAGS_host) $(CFLAGS_host) -CXX.host ?= %(CXX.host)s -CXXFLAGS.host ?= $(CPPFLAGS_host) $(CXXFLAGS_host) -LINK.host ?= %(LINK.host)s -LDFLAGS.host ?= -AR.host ?= %(AR.host)s - -# Define a dir function that can handle spaces. -# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions -# "leading spaces cannot appear in the text of the first argument as written. -# These characters can be put into the argument value by variable substitution." -empty := -space := $(empty) $(empty) - -# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces -replace_spaces = $(subst $(space),""" + SPACE_REPLACEMENT + """,$1) -unreplace_spaces = $(subst """ + SPACE_REPLACEMENT + """,$(space),$1) -dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1))) - -# Flags to make gcc output dependency info. Note that you need to be -# careful here to use the flags that ccache and distcc can understand. -# We write to a dep file on the side first and then rename at the end -# so we can't end up with a broken dep file. -depfile = $(depsdir)/$(call replace_spaces,$@).d -DEPFLAGS = -MMD -MF $(depfile).raw - -# We have to fixup the deps output in a few ways. -# (1) the file output should mention the proper .o file. -# ccache or distcc lose the path to the target, so we convert a rule of -# the form: -# foobar.o: DEP1 DEP2 -# into -# path/to/foobar.o: DEP1 DEP2 -# (2) we want missing files not to cause us to fail to build. -# We want to rewrite -# foobar.o: DEP1 DEP2 \\ -# DEP3 -# to -# DEP1: -# DEP2: -# DEP3: -# so if the files are missing, they're just considered phony rules. -# We have to do some pretty insane escaping to get those backslashes -# and dollar signs past make, the shell, and sed at the same time. -# Doesn't work with spaces, but that's fine: .d files have spaces in -# their names replaced with other characters.""" -r""" -define fixup_dep -# The depfile may not exist if the input file didn't have any #includes. -touch $(depfile).raw -# Fixup path as in (1). -sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile) -# Add extra rules as in (2). -# We remove slashes and replace spaces with new lines; -# remove blank lines; -# delete the first line and append a colon to the remaining lines. -sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ - grep -v '^$$' |\ - sed -e 1d -e 's|$$|:|' \ - >> $(depfile) -rm $(depfile).raw -endef -""" -""" -# Command definitions: -# - cmd_foo is the actual command to run; -# - quiet_cmd_foo is the brief-output summary of the command. - -quiet_cmd_cc = CC($(TOOLSET)) $@ -cmd_cc = $(CC.$(TOOLSET)) -o $@ $< $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c +_dirname = os.path.dirname(os.path.abspath(__file__)) +with open(os.path.join(_dirname, 'Makefile.tmpl'), 'rt') as f: + file_content = f.read() + SHARED_HEADER = file_content.format(SPACE_REPLACEMENT=SPACE_REPLACEMENT) -quiet_cmd_cxx = CXX($(TOOLSET)) $@ -cmd_cxx = $(CXX.$(TOOLSET)) -o $@ $< $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -%(extra_commands)s -quiet_cmd_touch = TOUCH $@ -cmd_touch = touch $@ +SHARED_HEADER_SUFFIX_RULES_COMMENT1 = ("""\ +# Suffix rules, putting all outputs into $(obj). +""") -quiet_cmd_copy = COPY $@ -# send stderr to /dev/null to ignore messages when linking directories. -cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp %(copy_archive_args)s "$<" "$@") +SHARED_HEADER_SUFFIX_RULES_COMMENT2 = ("""\ +# Try building from generated source, too. +""") -%(link_commands)s -""" +header = """\ +# This file is generated by gyp; do not edit. -r""" -# Define an escape_quotes function to escape single quotes. -# This allows us to handle quotes properly as long as we always use -# use single quotes and escape_quotes. -escape_quotes = $(subst ','\'',$(1)) -# This comment is here just to include a ' to unconfuse syntax highlighting. -# Define an escape_vars function to escape '$' variable syntax. -# This allows us to read/write command lines with shell variables (e.g. -# $LD_LIBRARY_PATH), without triggering make substitution. -escape_vars = $(subst $$,$$$$,$(1)) -# Helper that expands to a shell command to echo a string exactly as it is in -# make. This uses printf instead of echo because printf's behaviour with respect -# to escape sequences is more portable than echo's across different shells -# (e.g., dash, bash). -exact_echo = printf '%%s\n' '$(call escape_quotes,$(1))' """ -""" -# Helper to compare the command we're about to run against the command -# we logged the last time we ran the command. Produces an empty -# string (false) when the commands match. -# Tricky point: Make has no string-equality test function. -# The kernel uses the following, but it seems like it would have false -# positives, where one string reordered its arguments. -# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \\ -# $(filter-out $(cmd_$@), $(cmd_$(1)))) -# We instead substitute each for the empty string into the other, and -# say they're equal if both substitutions produce the empty string. -# .d files contain """ + SPACE_REPLACEMENT + \ - """ instead of spaces, take that into account. -command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\\ - $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) - -# Helper that is non-empty when a prerequisite changes. -# Normally make does this implicitly, but we force rules to always run -# so we can check their command lines. -# $? -- new prerequisites -# $| -- order-only dependencies -prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) - -# Helper that executes all postbuilds until one fails. -define do_postbuilds - @E=0;\\ - for p in $(POSTBUILDS); do\\ - eval $$p;\\ - E=$$?;\\ - if [ $$E -ne 0 ]; then\\ - break;\\ - fi;\\ - done;\\ - if [ $$E -ne 0 ]; then\\ - rm -rf "$@";\\ - exit $$E;\\ - fi -endef - -# do_cmd: run a command via the above cmd_foo names, if necessary. -# Should always run for a given target to handle command-line changes. -# Second argument, if non-zero, makes it do asm/C/C++ dependency munging. -# Third argument, if non-zero, makes it do POSTBUILDS processing. -# Note: We intentionally do NOT call dirx for depfile, since it contains """ + \ - SPACE_REPLACEMENT + """ for -# spaces already and dirx strips the """ + SPACE_REPLACEMENT + \ - """ characters. -define do_cmd -$(if $(or $(command_changed),$(prereq_changed)), - @$(call exact_echo, $($(quiet)cmd_$(1))) - @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" - $(if $(findstring flock,$(word %(flock_index)d,$(cmd_$1))), - @$(cmd_$(1)) - @echo " $(quiet_cmd_$(1)): Finished", - @$(cmd_$(1)) - ) - @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) - @$(if $(2),$(fixup_dep)) - $(if $(and $(3), $(POSTBUILDS)), - $(call do_postbuilds) - ) -) -endef - -# Declare the "%(default_target)s" target first so it is the default, -# even though we don't have the deps yet. -.PHONY: %(default_target)s -%(default_target)s: - -# make looks for ways to re-generate included makefiles, but in our case, we -# don't have a direct way. Explicitly telling make that it has nothing to do -# for them makes it go faster. -%%.d: ; - -# Use FORCE_DO_CMD to force a target to run. Should be coupled with -# do_cmd. -.PHONY: FORCE_DO_CMD -FORCE_DO_CMD: - -""") -SHARED_HEADER_MAC_COMMANDS = """ -quiet_cmd_objc = CXX($(TOOLSET)) $@ -cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< - -quiet_cmd_objcxx = CXX($(TOOLSET)) $@ -cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< - -# Commands for precompiled header files. -quiet_cmd_pch_c = CXX($(TOOLSET)) $@ -cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< -quiet_cmd_pch_cc = CXX($(TOOLSET)) $@ -cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< -quiet_cmd_pch_m = CXX($(TOOLSET)) $@ -cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< -quiet_cmd_pch_mm = CXX($(TOOLSET)) $@ -cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< - -# gyp-mac-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_mac_tool = MACTOOL $(4) $< -cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@" - -quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@ -cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4) - -quiet_cmd_infoplist = INFOPLIST $@ -cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@" -""" +# Maps every compilable file extension to the do_cmd that compiles it. +COMPILABLE_EXTENSIONS = { + '.c': 'cc', + '.cc': 'cxx', + '.cpp': 'cxx', + '.cxx': 'cxx', + '.s': 'cc', + '.S': 'cc', + '.m': 'objc', + '.mm': 'objcxx', +} def WriteRootHeaderSuffixRules(writer): @@ -513,8 +62,7 @@ def WriteRootHeaderSuffixRules(writer): writer.write('\n# Try building from generated source, too.\n') for ext in extensions: - writer.write( - '$(obj).$(TOOLSET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD\n' % ext) + writer.write('$(obj).$(TOOLSET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD\n' % ext) writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext]) writer.write('\n') for ext in extensions: @@ -523,44 +71,6 @@ def WriteRootHeaderSuffixRules(writer): writer.write('\n') -SHARED_HEADER_SUFFIX_RULES_COMMENT1 = ("""\ -# Suffix rules, putting all outputs into $(obj). -""") - - -SHARED_HEADER_SUFFIX_RULES_COMMENT2 = ("""\ -# Try building from generated source, too. -""") - - -SHARED_FOOTER = """\ -# "all" is a concatenation of the "all" targets from all the included -# sub-makefiles. This is just here to clarify. -all: - -# Add in dependency-tracking rules. $(all_deps) is the list of every single -# target in our tree. Only consider the ones with .d (dependency) info: -d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) -ifneq ($(d_files),) - include $(d_files) -endif -""" - -header = """\ -# This file is generated by gyp; do not edit. - -""" - -# Maps every compilable file extension to the do_cmd that compiles it. -COMPILABLE_EXTENSIONS = { - '.c': 'cc', - '.cc': 'cxx', - '.cpp': 'cxx', - '.cxx': 'cxx', - '.s': 'cc', - '.S': 'cc', -} - def Compilable(filename): """Return true if the file is compilable (should be in OBJS).""" for res in (filename.endswith(e) for e in COMPILABLE_EXTENSIONS): @@ -569,6 +79,16 @@ def Compilable(filename): return False + +# Map from qualified target to path to output. +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 = {} + + def Linkable(filename): """Return true if the file is linkable (should be on the link line).""" return filename.endswith('.o') @@ -580,16 +100,15 @@ def Target(filename): def EscapeShellArgument(s): - """Quotes an argument so that it will be interpreted literally by a POSIX - shell. Taken from - http://stackoverflow.com/questions/35817/whats-the-best-way-to-escape-ossystem-calls-in-python - """ + """ + Quotes an argument so that it will be interpreted literally by a POSIX shell. + Taken from http://stackoverflow.com/questions/35817/whats-the-best-way-to-escape-ossystem-calls-in-python + """ return "'" + s.replace("'", "'\\''") + "'" def EscapeMakeVariableExpansion(s): - """Make has its own variable expansion syntax using $. We must escape it for - string to be interpreted literally.""" + """Make has its own variable expansion syntax using $. We must escape it for string to be interpreted literally.""" return s.replace('$', '$$') @@ -603,8 +122,7 @@ def EscapeCppDefine(s): def QuoteIfNecessary(string): - """TODO: Should this ideally be replaced with one or more of the above - functions?""" + """TODO: Should this ideally be replaced with one or more of the above functions?""" if '"' in string: string = '"' + string.replace('"', '\\"') + '"' return string @@ -615,14 +133,14 @@ def StringToMakefileVariable(string): return re.sub('[^a-zA-Z0-9_]', '_', string) -srcdir_prefix = '' def Sourceify(path): """Convert a path to its source directory form.""" if '$(' in path: return path if os.path.isabs(path): return path - return srcdir_prefix + path + return Sourceify.srcdir_prefix + path +Sourceify.srcdir_prefix = '' def QuoteSpaces(s, quote=r'\ '): @@ -631,7 +149,8 @@ def QuoteSpaces(s, quote=r'\ '): # 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. + """ + Makes sure if duplicate basenames are not specified in the source list. Arguments: spec: The target dictionary containing the properties of the target. @@ -642,34 +161,23 @@ def _ValidateSourcesForOSX(spec, all_sources): 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'] + 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(): + for basename, files in basenames.items(): 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.') + print('static library %s%s libtool on OS X will generate warnings for them. has several files with the same basename:\n' % (spec['target_name'], error)) 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 -# 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 = {} - - +# noinspection PyAttributeOutsideInit class MakefileWriter(object): """MakefileWriter packages up the writing of one target-specific foobar.mk. @@ -687,35 +195,40 @@ def __init__(self, generator_flags, flavor): # Generate suffix rules for all compilable extensions. for ext in COMPILABLE_EXTENSIONS.keys(): # Suffix rules for source folder. - self.suffix_rules_srcdir.update({ext: ("""\ + self.suffix_rules_srcdir.update({ + ext: ("""\ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(srcdir)/%%%s FORCE_DO_CMD @$(call do_cmd,%s,1) -""" % (ext, COMPILABLE_EXTENSIONS[ext]))}) +""" % (ext, COMPILABLE_EXTENSIONS[ext])) + }) # Suffix rules for generated source files. - self.suffix_rules_objdir1.update({ext: ("""\ + self.suffix_rules_objdir1.update({ + ext: ("""\ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD @$(call do_cmd,%s,1) -""" % (ext, COMPILABLE_EXTENSIONS[ext]))}) - self.suffix_rules_objdir2.update({ext: ("""\ +""" % (ext, COMPILABLE_EXTENSIONS[ext])) + }) + self.suffix_rules_objdir2.update({ + ext: ("""\ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD @$(call do_cmd,%s,1) -""" % (ext, COMPILABLE_EXTENSIONS[ext]))}) - +""" % (ext, COMPILABLE_EXTENSIONS[ext])) + }) - def Write(self, qualified_target, base_path, output_filename, spec, configs, - part_of_all): - """The main entry point: writes a .mk file for a single target. + def Write(self, qualified_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 - base_path: path relative to source root we're building in, used to resolve - target-relative paths + 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 + spec: gyp info + configs: gyp info part_of_all: flag indicating this target is part of 'all' """ - gyp.common.EnsureDirExists(output_filename) + EnsureDirExists(output_filename) self.fp = open(output_filename, 'w') @@ -727,9 +240,9 @@ def Write(self, qualified_target, base_path, output_filename, spec, configs, self.type = spec['type'] self.toolset = spec['toolset'] - self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec) + self.is_mac_bundle = xcode_emulation.IsMacBundle(self.flavor, spec) if self.flavor == 'mac': - self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec) + self.xcode_settings = xcode_emulation.XcodeSettings(spec) else: self.xcode_settings = None @@ -745,15 +258,14 @@ def Write(self, qualified_target, base_path, output_filename, spec, configs, mac_bundle_deps = [] if self.is_mac_bundle: - self.output = self.ComputeMacBundleOutput(spec) - self.output_binary = self.ComputeMacBundleBinaryOutput(spec) + self.output = self.ComputeMacBundleOutput() + self.output_binary = self.ComputeMacBundleBinaryOutput() else: self.output = self.output_binary = self.ComputeOutput(spec) self.is_standalone_static_library = bool( - spec.get('standalone_static_library', 0)) - self._INSTALLABLE_TARGETS = ('executable', 'loadable_module', - 'shared_library') + spec.get('standalone_static_library', 0)) + self._INSTALLABLE_TARGETS = ('executable', 'loadable_module', 'shared_library') if (self.is_standalone_static_library or self.type in self._INSTALLABLE_TARGETS): self.alias = os.path.basename(self.output) @@ -772,18 +284,17 @@ def Write(self, qualified_target, base_path, output_filename, spec, configs, # Rules must be early like actions. if 'rules' in spec: - self.WriteRules(spec['rules'], extra_sources, extra_outputs, - extra_mac_bundle_resources, part_of_all) + self.WriteRules(spec['rules'], extra_sources, extra_outputs, extra_mac_bundle_resources) if 'copies' in spec: self.WriteCopies(spec['copies'], extra_outputs, part_of_all) # Bundle resources. if self.is_mac_bundle: - all_mac_bundle_resources = ( - spec.get('mac_bundle_resources', []) + extra_mac_bundle_resources) + all_mac_bundle_resources = spec.get('mac_bundle_resources', []) + extra_mac_bundle_resources self.WriteMacBundleResources(all_mac_bundle_resources, mac_bundle_deps) self.WriteMacInfoPlist(mac_bundle_deps) + self.WriteMacBundleResources(all_mac_bundle_resources, mac_bundle_deps) # Sources. all_sources = spec.get('sources', []) + extra_sources @@ -793,12 +304,10 @@ def Write(self, qualified_target, base_path, output_filename, spec, configs, # target. _ValidateSourcesForOSX(spec, all_sources) self.WriteSources( - configs, deps, all_sources, extra_outputs, - extra_link_deps, part_of_all, - gyp.xcode_emulation.MacPrefixHeader( - self.xcode_settings, lambda p: Sourceify(self.Absolutify(p)), - self.Pchify)) - sources = filter(Compilable, all_sources) + configs, deps, all_sources, extra_outputs, extra_link_deps, + gyp.xcode_emulation.MacPrefixHeader(self.xcode_settings, lambda p: Sourceify(self.Absolutify(p)), self.Pchify) + ) + sources = [x for x in all_sources if Compilable(x)] if sources: self.WriteLn(SHARED_HEADER_SUFFIX_RULES_COMMENT1) extensions = set([os.path.splitext(s)[1] for s in sources]) @@ -835,7 +344,6 @@ def Write(self, qualified_target, base_path, output_filename, spec, configs, self.fp.close() - def WriteSubMake(self, output_filename, makefile_path, targets, build_dir): """Write a "sub-project" Makefile. @@ -862,7 +370,6 @@ def WriteSubMake(self, output_filename, makefile_path, targets, build_dir): self.WriteLn('\t$(MAKE)%s %s' % (makefile_path, ' '.join(targets))) self.fp.close() - def WriteActions(self, actions, extra_sources, extra_outputs, extra_mac_bundle_resources, part_of_all): """Write Makefile code for any 'actions' from the gyp input. @@ -886,9 +393,9 @@ def WriteActions(self, actions, extra_sources, extra_outputs, # Collect the output dirs we'll need. dirs = set() for out in outputs: - dir = os.path.split(out)[0] - if dir: - dirs.add(dir) + d = os.path.split(out)[0] + if d: + dirs.add(d) if int(action.get('process_outputs_as_sources', False)): extra_sources += outputs if int(action.get('process_outputs_as_mac_bundle_resources', False)): @@ -897,8 +404,7 @@ def WriteActions(self, actions, extra_sources, extra_outputs, # Write the actual command. action_commands = action['action'] if self.flavor == 'mac': - action_commands = [gyp.xcode_emulation.ExpandEnvVars(command, env) - for command in action_commands] + action_commands = [gyp.xcode_emulation.ExpandEnvVars(command, env) for command in action_commands] command = gyp.common.EncodePOSIXShellList(action_commands) if 'message' in action: self.WriteLn('quiet_cmd_%s = ACTION %s $@' % (name, action['message'])) @@ -927,7 +433,7 @@ def WriteActions(self, actions, extra_sources, extra_outputs, '%s%s' % (name, cd_action, command)) self.WriteLn() - outputs = map(self.Absolutify, outputs) + outputs = [self.Absolutify(o) for o in outputs] # The makefile rules are all relative to the top dir, but the gyp actions # are defined relative to their containing dir. This replaces the obj # variable for the action rule with an absolute version so that the output @@ -940,19 +446,16 @@ def WriteActions(self, actions, extra_sources, extra_outputs, self.WriteLn("%s: builddir := $(abs_builddir)" % QuoteSpaces(outputs[0])) self.WriteSortedXcodeEnv(outputs[0], self.GetSortedXcodeEnv()) - for input in inputs: - assert ' ' not in input, ( - "Spaces in action input filenames not supported (%s)" % input) + for i in inputs: + assert ' ' not in i, ("Spaces in action input filenames not supported (%s)" % i) for output in outputs: - assert ' ' not in output, ( - "Spaces in action output filenames not supported (%s)" % output) + assert ' ' not in output, ("Spaces in action output filenames not supported (%s)" % output) # See the comment in WriteCopies about expanding env vars. outputs = [gyp.xcode_emulation.ExpandEnvVars(o, env) for o in outputs] inputs = [gyp.xcode_emulation.ExpandEnvVars(i, env) for i in inputs] - self.WriteDoCmd(outputs, map(Sourceify, map(self.Absolutify, inputs)), - part_of_all=part_of_all, command=name) + self.WriteDoCmd(outputs, map(Sourceify, map(self.Absolutify, inputs)), part_of_all=part_of_all, command=name) # Stuff the outputs in a variable so we can refer to them later. outputs_variable = 'action_%s_outputs' % name @@ -962,9 +465,7 @@ def WriteActions(self, actions, extra_sources, extra_outputs, self.WriteLn() - - def WriteRules(self, rules, extra_sources, extra_outputs, - extra_mac_bundle_resources, part_of_all): + def WriteRules(self, rules, extra_sources, extra_outputs, extra_mac_bundle_resources): """Write Makefile code for any 'rules' from the gyp input. extra_sources: a list that will be filled in with newly generated source @@ -985,17 +486,16 @@ def WriteRules(self, rules, extra_sources, extra_outputs, for rule_source in rule.get('rule_sources', []): dirs = set() (rule_source_dirname, rule_source_basename) = os.path.split(rule_source) - (rule_source_root, rule_source_ext) = \ - os.path.splitext(rule_source_basename) + (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']] for out in outputs: - dir = os.path.dirname(out) - if dir: - dirs.add(dir) + d = os.path.dirname(out) + if d: + dirs.add(d) if int(rule.get('process_outputs_as_sources', False)): extra_sources += outputs if int(rule.get('process_outputs_as_mac_bundle_resources', False)): @@ -1017,7 +517,7 @@ def WriteRules(self, rules, extra_sources, extra_outputs, outputs = [gyp.xcode_emulation.ExpandEnvVars(o, env) for o in outputs] inputs = [gyp.xcode_emulation.ExpandEnvVars(i, env) for i in inputs] - outputs = map(self.Absolutify, outputs) + outputs = [self.Absolutify(o) for o in outputs] all_outputs += outputs # Only write the 'obj' and 'builddir' rules for the "primary" output # (:1); it's superfluous for the "extra outputs", and this avoids @@ -1034,7 +534,7 @@ def WriteRules(self, rules, extra_sources, extra_outputs, for output in outputs: output = re.sub(variables_with_spaces, '', output) assert ' ' not in output, ( - "Spaces in rule filenames not yet supported (%s)" % output) + "Spaces in rule filenames not yet supported (%s)" % output) self.WriteLn('all_deps += %s' % ' '.join(outputs)) action = [self.ExpandInputRoot(ac, rule_source_root, @@ -1090,7 +590,6 @@ def WriteRules(self, rules, extra_sources, extra_outputs, self.WriteLn('### Finished generating for all rules') self.WriteLn('') - def WriteCopies(self, copies, extra_outputs, part_of_all): """Write Makefile code for any 'copies' from the gyp input. @@ -1128,52 +627,45 @@ def WriteCopies(self, copies, extra_outputs, part_of_all): extra_outputs.append('$(%s)' % variable) self.WriteLn() - def WriteMacBundleResources(self, resources, bundle_deps): """Writes Makefile code for 'mac_bundle_resources'.""" self.WriteLn('### Generated for mac_bundle_resources') - for output, res in gyp.xcode_emulation.GetMacBundleResources( - generator_default_variables['PRODUCT_DIR'], self.xcode_settings, - map(Sourceify, map(self.Absolutify, resources))): + product_dir = generator_default_variables['PRODUCT_DIR'] + sources = map(Sourceify, map(self.Absolutify, resources)) + bundle_resources = gyp.xcode_emulation.GetMacBundleResources(product_dir, self.xcode_settings, sources) + for output, res in bundle_resources: _, ext = os.path.splitext(output) + # TODO(refack): actualy figure this out for `copy-bundle-resource` + # is_binary = xcode_emulation.IsBinaryOutputFormat(output) if ext != '.xcassets': # Make does not supports '.xcassets' emulation. - self.WriteDoCmd([output], [res], 'mac_tool,,,copy-bundle-resource', - part_of_all=True) + self.WriteDoCmd([output], [res], 'mac_tool,,,copy-bundle-resource', part_of_all=True) bundle_deps.append(output) - def WriteMacInfoPlist(self, bundle_deps): """Write Makefile code for bundle Info.plist files.""" info_plist, out, defines, extra_env = gyp.xcode_emulation.GetMacInfoPlist( - generator_default_variables['PRODUCT_DIR'], self.xcode_settings, - lambda p: Sourceify(self.Absolutify(p))) + generator_default_variables['PRODUCT_DIR'], self.xcode_settings, + lambda p: Sourceify(self.Absolutify(p))) if not info_plist: return if defines: # Create an intermediate file to store preprocessed results. - intermediate_plist = ('$(obj).$(TOOLSET)/$(TARGET)/' + - os.path.basename(info_plist)) - self.WriteList(defines, intermediate_plist + ': INFOPLIST_DEFINES', '-D', - quoter=EscapeCppDefine) + intermediate_plist = ('$(obj).$(TOOLSET)/$(TARGET)/' + os.path.basename(info_plist)) + self.WriteList(defines, intermediate_plist + ': INFOPLIST_DEFINES', '-D', quoter=EscapeCppDefine) self.WriteMakeRule([intermediate_plist], [info_plist], - ['$(call do_cmd,infoplist)', - # "Convert" the plist so that any weird whitespace changes from the - # preprocessor do not affect the XML parser in mac_tool. - '@plutil -convert xml1 $@ $@']) + ['$(call do_cmd,infoplist)', + # "Convert" the plist so that any weird whitespace changes from the + # preprocessor do not affect the XML parser in mac_tool. + '@plutil -convert xml1 $@ $@']) info_plist = intermediate_plist # plists can contain envvars and substitute them into the file. - self.WriteSortedXcodeEnv( - out, self.GetSortedXcodeEnv(additional_settings=extra_env)) - self.WriteDoCmd([out], [info_plist], 'mac_tool,,,copy-info-plist', - part_of_all=True) + self.WriteSortedXcodeEnv(out, self.GetSortedXcodeEnv(additional_settings=extra_env)) + self.WriteDoCmd([out], [info_plist], 'mac_tool,,,copy-info-plist', part_of_all=True) bundle_deps.append(out) - - def WriteSources(self, configs, deps, sources, - extra_outputs, extra_link_deps, - part_of_all, precompiled_header): + def WriteSources(self, configs, deps, sources, extra_outputs, extra_link_deps, precompiled_header): """Write Makefile code for any 'sources' from the gyp input. These are source files necessary to build the current target. @@ -1188,8 +680,7 @@ def WriteSources(self, configs, deps, sources, # Write configuration-specific variables for CFLAGS, etc. for configname in sorted(configs.keys()): config = configs[configname] - self.WriteList(config.get('defines'), 'DEFS_%s' % configname, prefix='-D', - quoter=EscapeCppDefine) + self.WriteList(config.get('defines'), 'DEFS_%s' % configname, prefix='-D', quoter=EscapeCppDefine) if self.flavor == 'mac': cflags = self.xcode_settings.GetCflags(configname) @@ -1201,30 +692,32 @@ def WriteSources(self, configs, deps, sources, cflags = config.get('cflags') cflags_c = config.get('cflags_c') cflags_cc = config.get('cflags_cc') + cflags_objc = None + cflags_objcc = None - self.WriteLn("# Flags passed to all source files."); + self.WriteLn("# Flags passed to all source files.") self.WriteList(cflags, 'CFLAGS_%s' % configname) - self.WriteLn("# Flags passed to only C files."); + self.WriteLn("# Flags passed to only C files.") self.WriteList(cflags_c, 'CFLAGS_C_%s' % configname) - self.WriteLn("# Flags passed to only C++ files."); + self.WriteLn("# Flags passed to only C++ files.") self.WriteList(cflags_cc, 'CFLAGS_CC_%s' % configname) if self.flavor == 'mac': - self.WriteLn("# Flags passed to only ObjC files."); + self.WriteLn("# Flags passed to only ObjC files.") self.WriteList(cflags_objc, 'CFLAGS_OBJC_%s' % configname) - self.WriteLn("# Flags passed to only ObjC++ files."); + self.WriteLn("# Flags passed to only ObjC++ files.") self.WriteList(cflags_objcc, 'CFLAGS_OBJCC_%s' % configname) includes = config.get('include_dirs') if includes: - includes = map(Sourceify, map(self.Absolutify, includes)) + includes = [Sourceify(self.Absolutify(include)) for include in includes] self.WriteList(includes, 'INCS_%s' % configname, prefix='-I') compilable = filter(Compilable, sources) - objs = map(self.Objectify, map(self.Absolutify, map(Target, compilable))) + objs = [self.Objectify(self.Absolutify(Target(x))) for x in compilable] self.WriteList(objs, 'OBJS') for obj in objs: assert ' ' not in obj, ( - "Spaces in object filenames not supported (%s)" % obj) + "Spaces in object filenames not supported (%s)" % obj) self.WriteLn('# Add to the list of files we specially track ' 'dependencies for.') self.WriteLn('all_deps += $(OBJS)') @@ -1233,20 +726,18 @@ def WriteSources(self, configs, deps, sources, # Make sure our dependencies are built first. if deps: self.WriteMakeRule(['$(OBJS)'], deps, - comment = 'Make sure our dependencies are built ' - 'before any of us.', - order_only = True) + comment='Make sure our dependencies are built before any of us.', + order_only=True) # Make sure the actions and rules run first. # If they generate any extra headers etc., the per-.o file dep tracking # will catch the proper rebuilds, so order only is still ok here. if extra_outputs: self.WriteMakeRule(['$(OBJS)'], extra_outputs, - comment = 'Make sure our actions/rules run ' - 'before any of us.', - order_only = True) + comment='Make sure our actions/rules run before any of us.', + order_only=True) - pchdeps = precompiled_header.GetObjDependencies(compilable, objs ) + pchdeps = precompiled_header.GetObjDependencies(compilable, objs) if pchdeps: self.WriteLn('# Dependencies from obj files to their precompiled headers') for source, obj, gch in pchdeps: @@ -1291,7 +782,7 @@ def WriteSources(self, configs, deps, sources, # If there are any object files in our input file list, link them into our # output. - extra_link_deps += filter(Linkable, sources) + extra_link_deps += [source for source in sources if Linkable(source)] self.WriteLn() @@ -1300,7 +791,7 @@ def WritePchTargets(self, pch_commands): if not pch_commands: return - for gch, lang_flag, lang, input in pch_commands: + for gch, lang_flag, lang, inpt in pch_commands: extra_flags = { 'c': '$(CFLAGS_C_$(BUILDTYPE))', 'cc': '$(CFLAGS_CC_$(BUILDTYPE))', @@ -1319,15 +810,14 @@ def WritePchTargets(self, pch_commands): "$(CFLAGS_$(BUILDTYPE)) " + extra_flags) - self.WriteLn('%s: %s FORCE_DO_CMD' % (gch, input)) + self.WriteLn('%s: %s FORCE_DO_CMD' % (gch, inpt)) self.WriteLn('\t@$(call do_cmd,pch_%s,1)' % lang) self.WriteLn('') assert ' ' not in gch, ( - "Spaces in gch filenames not supported (%s)" % gch) + "Spaces in gch filenames not supported (%s)" % gch) self.WriteLn('all_deps += %s' % gch) self.WriteLn('') - def ComputeOutputBasename(self, spec): """Return the 'output basename' of a gyp spec. @@ -1359,8 +849,8 @@ def ComputeOutputBasename(self, spec): elif self.type == 'none': target = '%s.stamp' % target elif self.type != 'executable': - print ("ERROR: What output file should be generated?", - "type", self.type, "target", target) + print(("ERROR: What output file should be generated?", + "type", self.type, "target", target)) target_prefix = spec.get('product_prefix', target_prefix) target = spec.get('product_name', target) @@ -1370,11 +860,8 @@ def ComputeOutputBasename(self, spec): return target_prefix + target + target_ext - def _InstallImmediately(self): - return self.toolset == 'target' and self.flavor == 'mac' and self.type in ( - 'static_library', 'executable', 'shared_library', 'loadable_module') - + return self.toolset == 'target' and self.flavor == 'mac' and self.type in ('static_library', 'executable', 'shared_library', 'loadable_module') def ComputeOutput(self, spec): """Return the 'output' (full output path) of a gyp spec. @@ -1390,21 +877,19 @@ def ComputeOutput(self, spec): path = spec.get('product_dir', path) return os.path.join(path, self.ComputeOutputBasename(spec)) - - def ComputeMacBundleOutput(self, spec): + def ComputeMacBundleOutput(self): """Return the 'output' (full output path) to a bundle output directory.""" assert self.is_mac_bundle path = generator_default_variables['PRODUCT_DIR'] return os.path.join(path, self.xcode_settings.GetWrapperName()) - - def ComputeMacBundleBinaryOutput(self, spec): + def ComputeMacBundleBinaryOutput(self): """Return the 'output' (full output path) to the binary in a bundle.""" path = generator_default_variables['PRODUCT_DIR'] return os.path.join(path, self.xcode_settings.GetExecutablePath()) - - def ComputeDeps(self, spec): + @staticmethod + def ComputeDeps(spec): """Compute the dependencies of a gyp spec. Returns a tuple (deps, link_deps), where each is a list of @@ -1423,21 +908,19 @@ def ComputeDeps(self, spec): # TODO: It seems we need to transitively link in libraries (e.g. -lfoo)? # This hack makes it work: # link_deps.extend(spec.get('libraries', [])) - return (gyp.common.uniquer(deps), gyp.common.uniquer(link_deps)) + return gyp.common.uniquer(deps), gyp.common.uniquer(link_deps) + def WriteDependencyOnExtraOutputs(self, extra_outputs): + self.WriteMakeRule([self.output_binary], extra_outputs, comment='Build our special outputs first.', order_only=True) - def WriteDependencyOnExtraOutputs(self, target, extra_outputs): - self.WriteMakeRule([self.output_binary], extra_outputs, - comment = 'Build our special outputs first.', - order_only = True) - - - def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps, - extra_outputs, part_of_all): - """Write Makefile code to produce the final target of the gyp spec. + def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps, extra_outputs, 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() + spec: input from gyp. + configs: input from gyp. + deps: dependency lists; see ComputeDeps() + link_deps: dependency lists; see ComputeDeps() extra_outputs: any extra outputs that our target should depend on part_of_all: flag indicating this target is part of 'all' """ @@ -1445,11 +928,8 @@ def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps, self.WriteLn('### Rules for final target.') if extra_outputs: - self.WriteDependencyOnExtraOutputs(self.output_binary, extra_outputs) - self.WriteMakeRule(extra_outputs, deps, - comment=('Preserve order dependency of ' - 'special output on deps.'), - order_only = True) + self.WriteDependencyOnExtraOutputs(extra_outputs) + self.WriteMakeRule(extra_outputs, deps, comment='Preserve order dependency of special output on deps.', order_only=True) target_postbuilds = {} if self.type != 'none': @@ -1457,17 +937,15 @@ def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps, config = configs[configname] if self.flavor == 'mac': ldflags = self.xcode_settings.GetLdflags(configname, - generator_default_variables['PRODUCT_DIR'], - lambda p: Sourceify(self.Absolutify(p))) + generator_default_variables['PRODUCT_DIR'], + lambda p: Sourceify(self.Absolutify(p))) # TARGET_POSTBUILDS_$(BUILDTYPE) is added to postbuilds later on. gyp_to_build = gyp.common.InvertRelativePath(self.path) target_postbuild = self.xcode_settings.AddImplicitPostbuilds( - configname, - QuoteSpaces(os.path.normpath(os.path.join(gyp_to_build, - self.output))), - QuoteSpaces(os.path.normpath(os.path.join(gyp_to_build, - self.output_binary)))) + configname, + QuoteSpaces(os.path.normpath(os.path.join(gyp_to_build, self.output))), + QuoteSpaces(os.path.normpath(os.path.join(gyp_to_build, self.output_binary)))) if target_postbuild: target_postbuilds[configname] = target_postbuild else: @@ -1492,13 +970,11 @@ def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps, if self.flavor == 'mac': libraries = self.xcode_settings.AdjustLibraries(libraries) self.WriteList(libraries, 'LIBS') - self.WriteLn('%s: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))' % - QuoteSpaces(self.output_binary)) + self.WriteLn('%s: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))' % QuoteSpaces(self.output_binary)) self.WriteLn('%s: LIBS := $(LIBS)' % QuoteSpaces(self.output_binary)) if self.flavor == 'mac': - self.WriteLn('%s: GYP_LIBTOOLFLAGS := $(LIBTOOLFLAGS_$(BUILDTYPE))' % - QuoteSpaces(self.output_binary)) + self.WriteLn('%s: GYP_LIBTOOLFLAGS := $(LIBTOOLFLAGS_$(BUILDTYPE))' % QuoteSpaces(self.output_binary)) # Postbuild actions. Like actions, but implicitly depend on the target's # output. @@ -1506,8 +982,7 @@ def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps, if self.flavor == 'mac': if target_postbuilds: postbuilds.append('$(TARGET_POSTBUILDS_$(BUILDTYPE))') - postbuilds.extend( - gyp.xcode_emulation.GetSpecPostbuildCommands(spec)) + postbuilds.extend(gyp.xcode_emulation.GetSpecPostbuildCommands(spec)) if postbuilds: # Envvars may be referenced by TARGET_POSTBUILDS_$(BUILDTYPE), @@ -1516,20 +991,17 @@ def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps, self.WriteSortedXcodeEnv(self.output, self.GetSortedXcodePostbuildEnv()) for configname in target_postbuilds: - self.WriteLn('%s: TARGET_POSTBUILDS_%s := %s' % - (QuoteSpaces(self.output), - configname, - gyp.common.EncodePOSIXShellList(target_postbuilds[configname]))) + self.WriteLn('%s: TARGET_POSTBUILDS_%s := %s' % (QuoteSpaces(self.output), configname, gyp.common.EncodePOSIXShellList(target_postbuilds[configname]))) # Postbuilds expect to be run in the gyp file's directory, so insert an # implicit postbuild to cd to there. postbuilds.insert(0, gyp.common.EncodePOSIXShellList(['cd', self.path])) - for i in xrange(len(postbuilds)): - if not postbuilds[i].startswith('$'): - postbuilds[i] = EscapeShellArgument(postbuilds[i]) + for i, postbuild in enumerate(postbuilds): + if not postbuild.startswith('$'): + postbuilds[i] = EscapeShellArgument(postbuild) self.WriteLn('%s: builddir := $(abs_builddir)' % QuoteSpaces(self.output)) self.WriteLn('%s: POSTBUILDS := %s' % ( - QuoteSpaces(self.output), ' '.join(postbuilds))) + QuoteSpaces(self.output), ' '.join(postbuilds))) # A bundle directory depends on its dependencies such as bundle resources # and bundle binary. When all dependencies have been built, the bundle @@ -1537,7 +1009,7 @@ def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps, if self.is_mac_bundle: # If the framework doesn't contain a binary, then nothing depends # on the actions -- make the framework depend on them directly too. - self.WriteDependencyOnExtraOutputs(self.output, extra_outputs) + self.WriteDependencyOnExtraOutputs(extra_outputs) # Bundle dependencies. Note that the code below adds actions to this # target, so if you move these two lines, move the lines below as well. @@ -1547,8 +1019,7 @@ def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps, # After the framework is built, package it. Needs to happen before # postbuilds, since postbuilds depend on this. if self.type in ('shared_library', 'loadable_module'): - self.WriteLn('\t@$(call do_cmd,mac_package_framework,,,%s)' % - self.xcode_settings.GetFrameworkVersion()) + self.WriteLn('\t@$(call do_cmd,mac_package_framework,,,%s)' % self.xcode_settings.GetFrameworkVersion()) # Bundle postbuilds can depend on the whole bundle, so run them after # the bundle is packaged, not already after the bundle binary is done. @@ -1567,67 +1038,47 @@ def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps, self.WriteLn('\t@touch -c %s' % QuoteSpaces(self.output)) if postbuilds: - assert not self.is_mac_bundle, ('Postbuilds for bundles should be done ' - 'on the bundle, not the binary (target \'%s\')' % self.target) - assert 'product_dir' not in spec, ('Postbuilds do not work with ' - 'custom product_dir') + assert not self.is_mac_bundle, ('Postbuilds for bundles should be done on the bundle, not the binary (target \'%s\')' % self.target) + assert 'product_dir' not in spec, 'Postbuilds do not work with custom product_dir' if self.type == 'executable': - self.WriteLn('%s: LD_INPUTS := %s' % ( - QuoteSpaces(self.output_binary), - ' '.join(map(QuoteSpaces, link_deps)))) + self.WriteLn('%s: LD_INPUTS := %s' % (QuoteSpaces(self.output_binary), ' '.join(map(QuoteSpaces, link_deps)))) if self.toolset == 'host' and self.flavor == 'android': - self.WriteDoCmd([self.output_binary], link_deps, 'link_host', - part_of_all, postbuilds=postbuilds) + self.WriteDoCmd([self.output_binary], link_deps, 'link_host', part_of_all, postbuilds=postbuilds) else: - self.WriteDoCmd([self.output_binary], link_deps, 'link', part_of_all, - postbuilds=postbuilds) + self.WriteDoCmd([self.output_binary], link_deps, 'link', part_of_all, postbuilds=postbuilds) elif self.type == 'static_library': for link_dep in link_deps: - assert ' ' not in link_dep, ( - "Spaces in alink input filenames not supported (%s)" % link_dep) + assert ' ' not in link_dep, ("Spaces in alink input filenames not supported (%s)" % link_dep) if (self.flavor not in ('mac', 'openbsd', 'netbsd', 'win') and not - self.is_standalone_static_library): - self.WriteDoCmd([self.output_binary], link_deps, 'alink_thin', - part_of_all, postbuilds=postbuilds) + self.is_standalone_static_library): + self.WriteDoCmd([self.output_binary], link_deps, 'alink_thin', part_of_all, postbuilds=postbuilds) else: - self.WriteDoCmd([self.output_binary], link_deps, 'alink', part_of_all, - postbuilds=postbuilds) + self.WriteDoCmd([self.output_binary], link_deps, 'alink', part_of_all, postbuilds=postbuilds) elif self.type == 'shared_library': - self.WriteLn('%s: LD_INPUTS := %s' % ( - QuoteSpaces(self.output_binary), - ' '.join(map(QuoteSpaces, link_deps)))) - self.WriteDoCmd([self.output_binary], link_deps, 'solink', part_of_all, - postbuilds=postbuilds) + self.WriteLn('%s: LD_INPUTS := %s' % (QuoteSpaces(self.output_binary), ' '.join(map(QuoteSpaces, link_deps)))) + self.WriteDoCmd([self.output_binary], link_deps, 'solink', part_of_all, postbuilds=postbuilds) elif self.type == 'loadable_module': for link_dep in link_deps: - assert ' ' not in link_dep, ( - "Spaces in module input filenames not supported (%s)" % link_dep) + assert ' ' not in link_dep, ("Spaces in module input filenames not supported (%s)" % link_dep) if self.toolset == 'host' and self.flavor == 'android': - self.WriteDoCmd([self.output_binary], link_deps, 'solink_module_host', - part_of_all, postbuilds=postbuilds) + self.WriteDoCmd([self.output_binary], link_deps, 'solink_module_host', part_of_all, postbuilds=postbuilds) else: - self.WriteDoCmd( - [self.output_binary], link_deps, 'solink_module', part_of_all, - postbuilds=postbuilds) + self.WriteDoCmd([self.output_binary], link_deps, 'solink_module', part_of_all, postbuilds=postbuilds) elif self.type == 'none': # Write a stamp line. - self.WriteDoCmd([self.output_binary], deps, 'touch', part_of_all, - postbuilds=postbuilds) + self.WriteDoCmd([self.output_binary], deps, 'touch', part_of_all, postbuilds=postbuilds) else: - print "WARNING: no output for", self.type, target + print("WARNING: no output for", self.type, self.target) # Add an alias for each target (if there are any outputs). # Installable target aliases are created below. if ((self.output and self.output != self.target) and (self.type not in self._INSTALLABLE_TARGETS)): - self.WriteMakeRule([self.target], [self.output], - comment='Add target alias', phony = True) + self.WriteMakeRule([self.target], [self.output], comment='Add target alias', phony=True) if part_of_all: - self.WriteMakeRule(['all'], [self.target], - comment = 'Add target alias to "all" target.', - phony = True) + self.WriteMakeRule(['all'], [self.target], comment='Add target alias to "all" target.', phony=True) # Add special-case rules for our installable targets. # 1) They need to install to the build dir or "product" dir. @@ -1646,31 +1097,23 @@ def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps, if (self.flavor == 'mac' and not 'product_dir' in spec and self.toolset == 'target'): # On mac, products are created in install_path immediately. - assert install_path == self.output, '%s != %s' % ( - install_path, self.output) + assert install_path == self.output, '%s != %s' % (install_path, self.output) # Point the target alias to the final binary output. self.WriteMakeRule([self.target], [install_path], - comment='Add target alias', phony = True) + comment='Add target alias', phony=True) if install_path != self.output: assert not self.is_mac_bundle # See comment a few lines above. - self.WriteDoCmd([install_path], [self.output], 'copy', - comment = 'Copy this to the %s output path.' % - file_desc, part_of_all=part_of_all) + self.WriteDoCmd([install_path], [self.output], 'copy', comment='Copy this to the %s output path.' % file_desc, part_of_all=part_of_all) installable_deps.append(install_path) if self.output != self.alias and self.alias != self.target: - self.WriteMakeRule([self.alias], installable_deps, - comment = 'Short alias for building this %s.' % - file_desc, phony = True) + self.WriteMakeRule([self.alias], installable_deps, comment='Short alias for building this %s.' % file_desc, phony=True) if part_of_all: - self.WriteMakeRule(['all'], [install_path], - comment = 'Add %s to "all" target.' % file_desc, - phony = True) + self.WriteMakeRule(['all'], [install_path], comment='Add %s to "all" target.' % file_desc, phony=True) - - def WriteList(self, value_list, variable=None, prefix='', - quoter=QuoteIfNecessary): - """Write a variable definition that is a list of values. + def WriteList(self, value_list, variable=None, prefix='', quoter=QuoteIfNecessary): + """ + Write a variable definition that is a list of values. E.g. WriteList(['a','b'], 'foo', prefix='blah') writes out foo = blaha blahb @@ -1682,10 +1125,11 @@ def WriteList(self, value_list, variable=None, prefix='', values = ' \\\n\t' + ' \\\n\t'.join(value_list) self.fp.write('%s :=%s\n\n' % (variable, values)) - - def WriteDoCmd(self, outputs, inputs, command, part_of_all, comment=None, - postbuilds=False): - """Write a Makefile rule that uses do_cmd. + # TODO(refack) `part_of_all` is not used, but is part of signature used in many other places + # noinspection PyUnusedLocal + def WriteDoCmd(self, outputs, inputs, command, part_of_all=False, comment=None, postbuilds=None): + """ + Write a Makefile rule that uses do_cmd. This makes the outputs dependent on the command line that was run, as well as support the V= make command line flag. @@ -1694,11 +1138,14 @@ def WriteDoCmd(self, outputs, inputs, command, part_of_all, comment=None, if postbuilds: assert ',' not in command suffix = ',,1' # Tell do_cmd to honor $POSTBUILDS - self.WriteMakeRule(outputs, inputs, - actions = ['$(call do_cmd,%s%s)' % (command, suffix)], - comment = comment, - command = command, - force = True) + 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 # spaces with ? because escaping doesn't work with make's $(sort) and @@ -1706,10 +1153,9 @@ def WriteDoCmd(self, outputs, inputs, command, part_of_all, comment=None, outputs = [QuoteSpaces(o, SPACE_REPLACEMENT) for o in outputs] self.WriteLn('all_deps += %s' % ' '.join(outputs)) - - def WriteMakeRule(self, outputs, inputs, actions=None, comment=None, - order_only=False, force=False, phony=False, command=None): - """Write a Makefile rule, with some extra tricks. + def WriteMakeRule(self, outputs, inputs, actions=None, comment=None, 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 supported by make; see comments below) @@ -1723,7 +1169,7 @@ def WriteMakeRule(self, outputs, inputs, actions=None, comment=None, output is just a name to run the rule command: (optional) command name to generate unambiguous labels """ - outputs = map(QuoteSpaces, outputs) + outputs = [QuoteSpaces(o) for o in outputs] inputs = map(QuoteSpaces, inputs) if comment: @@ -1737,29 +1183,27 @@ def WriteMakeRule(self, outputs, inputs, actions=None, comment=None, 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)) + 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: + # 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 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. + # - The multi-output rule will have a do-nothing recipe. # Hash the target name to avoid generating overlong filenames. - cmddigest = hashlib.sha1(command if command else self.target).hexdigest() - intermediate = "%s.intermediate" % (cmddigest) + key = (command if command else self.target).encode('utf-8') + slug = re.sub(r'\w', key, '') + cmddigest = hashlib.sha1(key).hexdigest() + intermediate = "%s.%s.intermediate" % (cmddigest, slug) 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)) + self.WriteLn('%s: %s%s' % (intermediate, ' '.join(inputs), force_append)) actions.insert(0, '$(call do_cmd,touch)') if actions: @@ -1767,7 +1211,6 @@ def WriteMakeRule(self, outputs, inputs, actions=None, comment=None, self.WriteLn('\t%s' % action) self.WriteLn() - def WriteAndroidNdkModuleRule(self, module_name, all_sources, link_deps): """Write a set of LOCAL_XXX definitions for Android NDK. @@ -1821,9 +1264,9 @@ def WriteAndroidNdkModuleRule(self, module_name, all_sources, link_deps): def DepsToModules(deps, prefix, suffix): modules = [] for filepath in deps: - filename = os.path.basename(filepath) - if filename.startswith(prefix) and filename.endswith(suffix): - modules.append(filename[len(prefix):-len(suffix)]) + mod_filename = os.path.basename(filepath) + if mod_filename.startswith(prefix) and mod_filename.endswith(suffix): + modules.append(mod_filename[len(prefix):-len(suffix)]) return modules # Retrieve the default value of 'SHARED_LIB_SUFFIX' @@ -1832,15 +1275,11 @@ def DepsToModules(deps, prefix, suffix): CalculateVariables(default_variables, params) self.WriteList( - DepsToModules(link_deps, - generator_default_variables['SHARED_LIB_PREFIX'], - default_variables['SHARED_LIB_SUFFIX']), - 'LOCAL_SHARED_LIBRARIES') + DepsToModules(link_deps, generator_default_variables['SHARED_LIB_PREFIX'], default_variables['SHARED_LIB_SUFFIX']), + 'LOCAL_SHARED_LIBRARIES') self.WriteList( - DepsToModules(link_deps, - generator_default_variables['STATIC_LIB_PREFIX'], - generator_default_variables['STATIC_LIB_SUFFIX']), - 'LOCAL_STATIC_LIBRARIES') + DepsToModules(link_deps, generator_default_variables['STATIC_LIB_PREFIX'], generator_default_variables['STATIC_LIB_SUFFIX']), + 'LOCAL_STATIC_LIBRARIES') if self.type == 'executable': self.WriteLn('include $(BUILD_EXECUTABLE)') @@ -1850,28 +1289,19 @@ def DepsToModules(deps, prefix, suffix): self.WriteLn('include $(BUILD_STATIC_LIBRARY)') self.WriteLn() - def WriteLn(self, text=''): self.fp.write(text + '\n') - def GetSortedXcodeEnv(self, additional_settings=None): - return gyp.xcode_emulation.GetSortedXcodeEnv( - self.xcode_settings, "$(abs_builddir)", - os.path.join("$(abs_srcdir)", self.path), "$(BUILDTYPE)", - additional_settings) - + return gyp.xcode_emulation.GetSortedXcodeEnv(self.xcode_settings, "$(abs_builddir)", os.path.join("$(abs_srcdir)", self.path), "$(BUILDTYPE)", additional_settings) def GetSortedXcodePostbuildEnv(self): # CHROMIUM_STRIP_SAVE_FILE is a chromium-specific hack. # TODO(thakis): It would be nice to have some general mechanism instead. - strip_save_file = self.xcode_settings.GetPerTargetSetting( - 'CHROMIUM_STRIP_SAVE_FILE', '') + strip_save_file = self.xcode_settings.GetPerTargetSetting('CHROMIUM_STRIP_SAVE_FILE', '') # Even if strip_save_file is empty, explicitly write it. Else a postbuild # might pick up an export from an earlier target. - return self.GetSortedXcodeEnv( - additional_settings={'CHROMIUM_STRIP_SAVE_FILE': strip_save_file}) - + return self.GetSortedXcodeEnv(additional_settings={'CHROMIUM_STRIP_SAVE_FILE': strip_save_file}) def WriteSortedXcodeEnv(self, target, env): for k, v in env: @@ -1883,7 +1313,6 @@ def WriteSortedXcodeEnv(self, target, env): # So don't escape spaces in |env[k]|. self.WriteLn('%s: export %s := %s' % (QuoteSpaces(target), k, v)) - def Objectify(self, path): """Convert a path to its output directory form.""" if '$(' in path: @@ -1892,7 +1321,6 @@ def Objectify(self, path): path = '$(obj).%s/$(TARGET)/%s' % (self.toolset, path) return path - def Pchify(self, path, lang): """Convert a prefix header path to its output directory form.""" path = self.Absolutify(path) @@ -1902,7 +1330,6 @@ def Pchify(self, path, lang): return path return '$(obj).%s/$(TARGET)/pch-%s/%s' % (self.toolset, lang, path) - def Absolutify(self, path): """Convert a subdirectory-relative path into a base-relative path. Skips over paths that contain variables.""" @@ -1913,17 +1340,16 @@ def Absolutify(self, path): return path.rstrip('/') return os.path.normpath(os.path.join(self.path, path)) - - def ExpandInputRoot(self, template, expansion, dirname): + @staticmethod + def ExpandInputRoot(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, - } + 'INPUT_ROOT': expansion, + 'INPUT_DIRNAME': dirname, + } return path - def _InstallableTargetInstallPath(self): """Returns the location of the final output for an installable target.""" # Xcode puts shared_library results into PRODUCT_DIR, and some gyp files @@ -1934,296 +1360,3 @@ def _InstallableTargetInstallPath(self): # convenient access with LD_LIBRARY_PATH. return '$(builddir)/lib.%s/%s' % (self.toolset, self.alias) return '$(builddir)/' + self.alias - - -def WriteAutoRegenerationRule(params, root_makefile, makefile_name, - build_files): - """Write the target to regenerate the Makefile.""" - options = params['options'] - build_files_args = [gyp.common.RelativePath(filename, options.toplevel_dir) - for filename in params['build_files_arg']] - - gyp_binary = gyp.common.FixIfRelativePath(params['gyp_binary'], - options.toplevel_dir) - if not gyp_binary.startswith(os.sep): - gyp_binary = os.path.join('.', gyp_binary) - - root_makefile.write( - "quiet_cmd_regen_makefile = ACTION Regenerating $@\n" - "cmd_regen_makefile = cd $(srcdir); %(cmd)s\n" - "%(makefile_name)s: %(deps)s\n" - "\t$(call do_cmd,regen_makefile)\n\n" % { - 'makefile_name': makefile_name, - 'deps': ' '.join(map(Sourceify, build_files)), - 'cmd': gyp.common.EncodePOSIXShellList( - [gyp_binary, '-fmake'] + - gyp.RegenerateFlags(options) + - build_files_args)}) - - -def PerformBuild(data, configurations, params): - options = params['options'] - for config in configurations: - arguments = ['make'] - if options.toplevel_dir and options.toplevel_dir != '.': - arguments += '-C', options.toplevel_dir - arguments.append('BUILDTYPE=' + config) - print 'Building [%s]: %s' % (config, arguments) - subprocess.check_call(arguments) - - -def GenerateOutput(target_list, target_dicts, data, params): - options = params['options'] - flavor = gyp.common.GetFlavor(params) - generator_flags = params.get('generator_flags', {}) - builddir_name = generator_flags.get('output_dir', 'out') - android_ndk_version = generator_flags.get('android_ndk_version', None) - default_target = generator_flags.get('default_target', 'all') - - 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) - if options.generator_output: - 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 - - # 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 = 'Makefile' + options.suffix - makefile_path = os.path.join(options.toplevel_dir, makefile_name) - if options.generator_output: - global srcdir_prefix - makefile_path = os.path.join( - options.toplevel_dir, options.generator_output, makefile_name) - srcdir = gyp.common.RelativePath(srcdir, options.generator_output) - srcdir_prefix = '$(srcdir)/' - - flock_command= 'flock' - copy_archive_arguments = '-af' - header_params = { - 'default_target': default_target, - 'builddir': builddir_name, - 'default_configuration': default_configuration, - 'flock': flock_command, - 'flock_index': 1, - 'link_commands': LINK_COMMANDS_LINUX, - 'extra_commands': '', - 'srcdir': srcdir, - 'copy_archive_args': copy_archive_arguments, - } - if flavor == 'mac': - flock_command = './gyp-mac-tool flock' - header_params.update({ - 'flock': flock_command, - 'flock_index': 2, - 'link_commands': LINK_COMMANDS_MAC, - 'extra_commands': SHARED_HEADER_MAC_COMMANDS, - }) - elif flavor == 'android': - header_params.update({ - 'link_commands': LINK_COMMANDS_ANDROID, - }) - elif flavor == 'solaris': - header_params.update({ - 'flock': './gyp-flock-tool flock', - 'flock_index': 2, - }) - elif flavor == 'freebsd': - # Note: OpenBSD has sysutils/flock. lockf seems to be FreeBSD specific. - header_params.update({ - 'flock': 'lockf', - }) - elif flavor == 'openbsd': - copy_archive_arguments = '-pPRf' - header_params.update({ - 'copy_archive_args': copy_archive_arguments, - }) - elif flavor == 'aix': - copy_archive_arguments = '-pPRf' - header_params.update({ - 'copy_archive_args': copy_archive_arguments, - 'link_commands': LINK_COMMANDS_AIX, - 'flock': './gyp-flock-tool flock', - 'flock_index': 2, - }) - - header_params.update({ - 'CC.target': GetEnvironFallback(('CC_target', 'CC'), '$(CC)'), - 'AR.target': GetEnvironFallback(('AR_target', 'AR'), '$(AR)'), - 'CXX.target': GetEnvironFallback(('CXX_target', 'CXX'), '$(CXX)'), - 'LINK.target': GetEnvironFallback(('LINK_target', 'LINK'), '$(LINK)'), - 'CC.host': GetEnvironFallback(('CC_host', 'CC'), 'gcc'), - 'AR.host': GetEnvironFallback(('AR_host', 'AR'), 'ar'), - 'CXX.host': GetEnvironFallback(('CXX_host', 'CXX'), 'g++'), - 'LINK.host': GetEnvironFallback(('LINK_host', 'LINK'), '$(CXX.host)'), - }) - - build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) - make_global_settings_array = data[build_file].get('make_global_settings', []) - wrappers = {} - for key, value in make_global_settings_array: - if key.endswith('_wrapper'): - wrappers[key[:-len('_wrapper')]] = '$(abspath %s)' % value - make_global_settings = '' - for key, value in make_global_settings_array: - if re.match('.*_wrapper', key): - continue - if value[0] != '$': - value = '$(abspath %s)' % value - wrapper = wrappers.get(key) - if wrapper: - value = '%s %s' % (wrapper, value) - del wrappers[key] - if key in ('CC', 'CC.host', 'CXX', 'CXX.host'): - make_global_settings += ( - 'ifneq (,$(filter $(origin %s), undefined default))\n' % key) - # Let gyp-time envvars win over global settings. - 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: - make_global_settings += '%s ?= %s\n' % (key, value) - # TODO(ukai): define cmd when only wrapper is specified in - # make_global_settings. - - header_params['make_global_settings'] = make_global_settings - - 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 - # could be different. - if android_ndk_version: - root_makefile.write( - '# Define LOCAL_PATH for build of Android applications.\n' - 'LOCAL_PATH := $(call my-dir)\n' - '\n') - for toolset in toolsets: - root_makefile.write('TOOLSET := %s\n' % toolset) - WriteRootHeaderSuffixRules(root_makefile) - - # Put build-time support tools next to the root Makefile. - dest_path = os.path.dirname(makefile_path) - gyp.common.CopyTool(flavor, dest_path) - - # 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() - for qualified_target in target_list: - build_file, target, toolset = gyp.common.ParseQualifiedTarget( - qualified_target) - - 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. %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'] - 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'] - - if flavor == 'mac': - gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec) - - writer = MakefileWriter(generator_flags, flavor) - writer.Write(qualified_target, base_path, output_file, spec, configs, - part_of_all=qualified_target in needed_targets) - - # 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) - - # Write out per-gyp (sub-project) Makefiles. - depth_rel_path = gyp.common.RelativePath(options.depth, os.getcwd()) - for build_file in build_files: - # The paths in build_files were relativized above, so undo that before - # testing against the non-relativized items in target_list and before - # calculating the Makefile path. - build_file = os.path.join(depth_rel_path, build_file) - gyp_targets = [target_dicts[target]['target_name'] for target in target_list - if target.startswith(build_file) and - target in needed_targets] - # Only generate Makefiles for gyp files with targets. - if not gyp_targets: - continue - base_path, output_file = CalculateMakefilePath(build_file, - os.path.splitext(os.path.basename(build_file))[0] + '.Makefile') - makefile_rel_path = gyp.common.RelativePath(os.path.dirname(makefile_path), - os.path.dirname(output_file)) - writer.WriteSubMake(output_file, makefile_rel_path, gyp_targets, - builddir_name) - - - # Write out the sorted list of includes. - root_makefile.write('\n') - for include_file in sorted(include_list): - # We wrap each .mk include in an if statement so users can tell make to - # not load a file by setting NO_LOAD. The below make code says, only - # load the .mk file if the .mk filename doesn't start with a token in - # NO_LOAD. - root_makefile.write( - "ifeq ($(strip $(foreach prefix,$(NO_LOAD),\\\n" - " $(findstring $(join ^,$(prefix)),\\\n" - " $(join ^," + include_file + ")))),)\n") - root_makefile.write(" include " + include_file + "\n") - root_makefile.write("endif\n") - root_makefile.write('\n') - - if (not generator_flags.get('standalone') - and generator_flags.get('auto_regeneration', True)): - WriteAutoRegenerationRule(params, root_makefile, makefile_name, build_files) - - root_makefile.write(SHARED_FOOTER) - - root_makefile.close() diff --git a/tools/gyp/gyp/NinjaWriter.py b/tools/gyp/gyp/NinjaWriter.py new file mode 100644 index 00000000000000..055b750e23ae1e --- /dev/null +++ b/tools/gyp/gyp/NinjaWriter.py @@ -0,0 +1,1407 @@ +import copy +import hashlib +import json +import os.path +import re +import sys +from collections import OrderedDict + +import gyp +from gyp import msvs_emulation, xcode_emulation +from gyp.generator.ninja import generator_default_variables, OpenOutput, GetWinLinkRuleNameSuffix, CalculateVariables +from gyp.lib import ninja_syntax + + +class Target(object): + """Target represents the paths used within a single gyp target. + + Conceptually, building a single target A is a series of steps: + + 1) actions/rules/copies generates source/resources/etc. + 2) compiles generates .o files + 3) link generates a binary (library/executable) + 4) bundle merges the above in a mac bundle + + (Any of these steps can be optional.) + + From a build ordering perspective, a dependent target B could just + depend on the last output of this series of steps. + + But some dependent commands sometimes need to reach inside the box. + For example, when linking B it needs to get the path to the static + library generated by A. + + This object stores those paths. To keep things simple, member + variables only store concrete paths to single files, while methods + compute derived values like "the last output of the target". + """ + + def __init__(self, type_arg): + # Gyp type ("static_library", etc.) of this target. + self.type = type_arg + # File representing whether any input dependencies necessary for + # dependent actions have completed. + self.preaction_stamp = None + # File representing whether any input dependencies necessary for + # dependent compiles have completed. + self.precompile_stamp = None + # File representing the completion of actions/rules/copies, if any. + self.actions_stamp = None + # Path to the output of the link step, if any. + self.binary = None + # Path to the file representing the completion of building the bundle, + # if any. + self.bundle = None + # On Windows, incremental linking requires linking against all the .objs + # that compose a .lib (rather than the .lib itself). That list is stored + # here. In this case, we also need to save the compile_deps for the target, + # so that the the target that directly depends on the .objs can also depend + # on those. + self.component_objs = None + self.compile_deps = None + # Windows only. The import .lib is the output of a build step, but + # because dependents only link against the lib (not both the lib and the + # dll) we keep track of the import library here. + self.import_lib = None + # Track if this target contains any C++ files, to decide if gcc or g++ + # should be used for linking. + self.uses_cpp = False + + def Linkable(self): + """Return true if this is a target that can be linked against.""" + return self.type in ('static_library', 'shared_library') + + def UsesToc(self, flavor): + """Return true if the target should produce a restat rule based on a TOC + file.""" + # For bundles, the .TOC should be produced for the binary, not for + # FinalOutput(). But the naive approach would put the TOC file into the + # bundle, so don't do this for bundles for now. + if flavor == 'win' or self.bundle: + return False + return self.type in ('shared_library', 'loadable_module') + + def PreActionInput(self, flavor): + """Return the path, if any, that should be used as a dependency of + any dependent action step.""" + if self.UsesToc(flavor): + return self.FinalOutput() + '.TOC' + return self.FinalOutput() or self.preaction_stamp + + def PreCompileInput(self): + """Return the path, if any, that should be used as a dependency of + any dependent compile step.""" + return self.actions_stamp or self.precompile_stamp + + def FinalOutput(self): + """Return the last output of the target, which depends on all prior + steps.""" + return self.bundle or self.binary or self.actions_stamp + + +# A small discourse on paths as used within the Ninja build: +# All files we produce (both at gyp and at build time) appear in the build directory (e.g. out/Debug). +# +# Paths within a given .gyp file are always relative to the directory containing the .gyp file. Call these "gyp paths". +# This includes sources as well as the starting directory a given gyp rule/action expects to be run from. +# We call the path from the source root to the gyp file the "base directory" within the per-.gyp-file NinjaWriter code. +# +# All paths as written into the .ninja files are relative to the build directory. Call these paths "ninja paths". +# +# We translate between these two notions of paths with two helper functions: +# +# - NinjaWriter._GypPathToNinja translates a gyp path (i.e. relative to the .gyp file) into the equivalent ninja path. +# +# - NinjaWriter._GypPathToUniqueOutput translates a gyp path into a ninja path to write 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(object): + def __init__(self, hash_for_rules, target_outputs, base_dir, build_dir, output_file, toplevel_build, output_file_name, flavor, spec, generator_flags, config_name, toplevel_dir): + """ + base_dir: path from source root to directory containing this gyp file, + by gyp semantics, all input paths are relative to this + build_dir: path from source root to build output + toplevel_dir: path to the toplevel directory + """ + self.flavor = flavor + self.spec = spec + self.generator_flags = generator_flags + self.xcode_settings = self.msvs_settings = None + self.is_mac_bundle = xcode_emulation.IsMacBundle(self.flavor, spec) + self.target_rpath = self.generator_flags.get('target_rpath', r'\$$ORIGIN/lib/') + self.is_standalone_static_library = bool(spec.get('standalone_static_library', 0)) + self.target = Target(spec['type']) + self.toolset = spec['toolset'] + self.name = spec['target_name'] + self.config_name = config_name + self.config = spec['configurations'][self.config_name] + self.hash_for_rules = hash_for_rules + self.target_outputs = target_outputs + self.base_dir = base_dir + self.build_dir = build_dir + self.ninja = ninja_syntax.Writer(output_file) + self.toplevel_build = toplevel_build + self.output_file_name = output_file_name + self.archs = [] + self.arch_subninjas = [] + + self.abs_build_dir = None + if toplevel_dir is not None: + self.abs_build_dir = os.path.abspath(os.path.join(toplevel_dir, build_dir)) + self.obj_ext = '.obj' if flavor == 'win' else '.o' + if flavor == 'win': + # See docstring of msvs_emulation.GenerateEnvironmentFiles(). + self.win_env = {} + for arch in ('x86', 'x64'): + self.win_env[arch] = 'environment.' + arch + + # Relative path from build output dir to base dir. + build_to_top = gyp.common.InvertRelativePath(build_dir, toplevel_dir) + self.build_to_base = os.path.join(build_to_top, base_dir) + # 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) + + def _ExpandSpecial(self, path, product_dir=None): + """Expand specials like $!PRODUCT_DIR in |path|. + + If |product_dir| is None, assumes the cwd is already the product + dir. Otherwise, |product_dir| is the relative path to the product + dir. + """ + + PRODUCT_DIR = '$!PRODUCT_DIR' + if PRODUCT_DIR in path: + if product_dir: + path = path.replace(PRODUCT_DIR, product_dir) + else: + path = path.replace(PRODUCT_DIR + '/', '') + path = path.replace(PRODUCT_DIR + '\\', '') + path = path.replace(PRODUCT_DIR, '.') + + INTERMEDIATE_DIR = '$!INTERMEDIATE_DIR' + if INTERMEDIATE_DIR in path: + int_dir = self._GypPathToUniqueOutput('gen') + # _GypPathToUniqueOutput generates a path relative to the product dir, + # so insert product_dir in front if it is provided. + path = path.replace(INTERMEDIATE_DIR, os.path.join(product_dir or '', int_dir)) + + CONFIGURATION_NAME = '$|CONFIGURATION_NAME' + path = path.replace(CONFIGURATION_NAME, self.config_name) + + return path + + def _ExpandRuleVariables(self, path, root, dirname, source, ext, name): + if self.flavor == 'win': + path = self.msvs_settings.ConvertVSMacros(path, config=self.config_name) + path = path.replace(generator_default_variables['RULE_INPUT_ROOT'], root) + path = path.replace(generator_default_variables['RULE_INPUT_DIRNAME'], dirname) + path = path.replace(generator_default_variables['RULE_INPUT_PATH'], source) + path = path.replace(generator_default_variables['RULE_INPUT_EXT'], ext) + path = path.replace(generator_default_variables['RULE_INPUT_NAME'], name) + return path + + def _GypPathToNinja(self, path, env=None): + """Translate a gyp path to a ninja path, optionally expanding environment + variable references in |path| with |env|. + + See the above discourse on path conversions.""" + if env: + if self.flavor == 'mac': + path = gyp.xcode_emulation.ExpandEnvVars(path, env) + elif self.flavor == 'win': + path = gyp.msvs_emulation.ExpandMacros(path, env) + if path.startswith('$!'): + expanded = self._ExpandSpecial(path) + if self.flavor == 'win': + expanded = os.path.normpath(expanded) + return expanded + if '$|' in path: + path = self._ExpandSpecial(path) + assert '$' not in path, path + return os.path.normpath(os.path.join(self.build_to_base, path)) + + def _GypPathToUniqueOutput(self, path, qualified=True): + """Translate a gyp path to a ninja path for writing output. + + If qualified is True, qualify the resulting filename with the name + of the target. This is necessary when e.g. compiling the same + path twice for two separate output targets. + + See the above discourse on path conversions.""" + + path = self._ExpandSpecial(path) + assert not path.startswith('$'), path + + # Translate the path following this scheme: + # Input: foo/bar.gyp, target targ, references baz/out.o + # Output: obj/foo/baz/targ.out.o (if qualified) + # obj/foo/baz/out.o (otherwise) + # (and obj.host instead of obj for cross-compiles) + # + # Why this scheme and not some other one? + # 1) for a given input, you can compute all derived outputs by matching + # its path, even if the input is brought via a gyp file with '..'. + # 2) simple files like libraries and stamps have a simple filename. + + obj = 'obj' + if self.toolset != 'target': + 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, 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. + + Uses a stamp file if necessary.""" + + assert targets == [t for t in targets if t], targets + if len(targets) == 0: + assert not order_only + return None + if len(targets) > 1 or order_only: + stamp = self._GypPathToUniqueOutput(name + '.stamp') + targets = self.ninja.build(stamp, 'stamp', targets, order_only=order_only) + self.ninja.newline() + return targets[0] + + def _SubninjaNameForArch(self, arch): + output_file_base = os.path.splitext(self.output_file_name)[0] + return '%s.%s.ninja' % (output_file_base, arch) + + def _WinIdlRule(self, source, prebuild, outputs): + """Handle the implicit VS .idl rule for one source file. Fills |outputs| + with files that are generated.""" + outdir, output, raw_vars, flags = self.msvs_settings.GetIdlBuildData(source, self.config_name) + outdir = self._GypPathToNinja(outdir) + + def fix_path(path, rel=None): + path = os.path.join(outdir, path) + dirname, basename = os.path.split(source) + root, ext = os.path.splitext(basename) + path = self._ExpandRuleVariables(path, root, dirname, source, ext, basename) + if rel: + path = os.path.relpath(path, rel) + return path + + variables = [(name, fix_path(value, outdir)) for name, value in raw_vars] + output = [fix_path(p) for p in output] + variables.append(('outdir', outdir)) + variables.append(('idlflags', flags)) + inpt = self._GypPathToNinja(source) + self.ninja.build(output, 'idl', inpt, variables=variables, order_only=prebuild) + outputs.extend(output) + + def _WriteWinIdlFiles(self, spec, prebuild): + """Writes rules to match MSVS's implicit idl handling.""" + assert self.flavor == 'win' + if self.msvs_settings.HasExplicitIdlRulesOrActions(spec): + return [] + outputs = [] + for source in filter(lambda x: x.endswith('.idl'), spec['sources']): + self._WinIdlRule(source, prebuild, outputs) + return outputs + + def _WriteActionsRulesCopies(self, spec, extra_sources, prebuild, mac_bundle_depends): + """Write out the Actions, Rules, and Copies steps. Return a path + representing the outputs of these steps.""" + outputs = [] + if self.is_mac_bundle: + mac_bundle_resources = spec.get('mac_bundle_resources', [])[:] + else: + mac_bundle_resources = [] + extra_mac_bundle_resources = [] + + if 'actions' in spec: + outputs += self._WriteActions(spec['actions'], extra_sources, prebuild, extra_mac_bundle_resources) + if 'rules' in spec: + outputs += self._WriteRules(spec['rules'], extra_sources, prebuild, mac_bundle_resources, extra_mac_bundle_resources) + if 'copies' in spec: + outputs += self._WriteCopies(spec['copies'], prebuild, mac_bundle_depends) + + if 'sources' in spec and self.flavor == 'win': + outputs += self._WriteWinIdlFiles(spec, prebuild) + + if self.xcode_settings and self.xcode_settings.IsIosFramework(): + self._WriteIOSFrameworkHeaders(spec, outputs, prebuild) + + stamp = self._WriteCollapsedDependencies('actions_rules_copies', outputs) + + if self.is_mac_bundle: + 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 + + def _GenerateDescription(self, verb, message, fallback): + """Generate and return a description of a build step. + + |verb| is the short summary, e.g. ACTION or RULE. + |message| is a hand-written description, or None if not available. + |fallback| is the gyp-level name of the step, usable as a fallback. + """ + if self.toolset != 'target': + verb += '(%s)' % self.toolset + if message: + return '%s %s' % (verb, self._ExpandSpecial(message)) + else: + return '%s %s: %s' % (verb, self.name, fallback) + + def _WriteActions(self, actions, extra_sources, prebuild, extra_mac_bundle_resources): + # Actions cd into the base directory. + env = self._GetToolchainEnv() + all_outputs = [] + for action in actions: + # First write out a rule for the action. + 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, pool, depfile=depfile) + + inputs = [self._GypPathToNinja(i, env) for i in action['inputs']] + if int(action.get('process_outputs_as_sources', False)): + extra_sources += action['outputs'] + if int(action.get('process_outputs_as_mac_bundle_resources', False)): + extra_mac_bundle_resources += action['outputs'] + outputs = [self._GypPathToNinja(o, env) for o in action['outputs']] + + # Then write out an edge using the rule. + self.ninja.build(outputs, rule_name, inputs, order_only=prebuild) + all_outputs += outputs + + self.ninja.newline() + + return all_outputs + + def _WriteRules(self, rules, extra_sources, prebuild, mac_bundle_resources, extra_mac_bundle_resources): + env = self._GetToolchainEnv() + all_outputs = [] + for rule in rules: + # 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', rule.get('message', None), ('%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, pool) + + # TODO: if the command references the outputs directly, we should + # simplify it to just use $out. + + # Rules can potentially make use of some special variables which + # must vary per source file. + # Compute the list of variables we'll need to provide. + special_locals = ('source', 'root', 'dirname', 'ext', 'name') + needed_variables = {'source'} + for argument in args: + for var in special_locals: + if '${%s}' % var in argument: + needed_variables.add(var) + needed_variables = sorted(needed_variables) + + def cygwin_mung(path): + 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 sources: + source = os.path.normpath(source) + dirname, basename = os.path.split(source) + root, ext = os.path.splitext(basename) + + # Gather the list of inputs and outputs, expanding $vars if possible. + outputs = [self._ExpandRuleVariables(o, root, dirname, source, ext, basename) for o in rule['outputs']] + + if int(rule.get('process_outputs_as_sources', False)): + extra_sources += outputs + + was_mac_bundle_resource = source in mac_bundle_resources + if was_mac_bundle_resource or int(rule.get('process_outputs_as_mac_bundle_resources', False)): + extra_mac_bundle_resources += outputs + # Note: This is n_resources * n_outputs_in_rule. Put to-be-removed + # items in a set and remove them all in a single pass if this becomes + # a performance issue. + if was_mac_bundle_resource: + mac_bundle_resources.remove(source) + + extra_bindings = [] + for var in needed_variables: + if var == 'root': + extra_bindings.append(('root', cygwin_mung(root))) + elif var == 'dirname': + # '$dirname' is a parameter to the rule action, which means + # it shouldn't be converted to a Ninja path. But we don't + # want $!PRODUCT_DIR in there either. + dirname_expanded = self._ExpandSpecial(dirname, self.base_to_build) + extra_bindings.append(('dirname', cygwin_mung(dirname_expanded))) + elif var == 'source': + # '$source' is a parameter to the rule action, which means + # it shouldn't be converted to a Ninja path. But we don't + # want $!PRODUCT_DIR in there either. + source_expanded = self._ExpandSpecial(source, self.base_to_build) + extra_bindings.append(('source', cygwin_mung(source_expanded))) + elif var == 'ext': + extra_bindings.append(('ext', ext)) + elif var == 'name': + extra_bindings.append(('name', cygwin_mung(basename))) + else: + assert var is None, repr(var) + + outputs = [self._GypPathToNinja(o, env) for o in outputs] + if self.flavor == 'win': + # _WriteNewNinjaRule uses unique_name for creating an rsp file on win. + extra_bindings.append(('unique_name', hashlib.md5(outputs[0].encode('utf-8')).hexdigest())) + + self.ninja.build(outputs, rule_name, self._GypPathToNinja(source), implicit=inputs, order_only=prebuild, variables=extra_bindings) + + all_outputs.extend(outputs) + + return all_outputs + + def _WriteCopies(self, copies, prebuild, mac_bundle_depends): + outputs = [] + if self.xcode_settings: + extra_env = self.xcode_settings.GetPerTargetSettings() + env = self._GetToolchainEnv(additional_settings=extra_env) + else: + env = self._GetToolchainEnv() + for cpy in copies: + for path in cpy['files']: + # Normalize the path so trailing slashes don't confuse us. + path = os.path.normpath(path) + basename = os.path.split(path)[1] + src = self._GypPathToNinja(path, env) + dst = self._GypPathToNinja(os.path.join(cpy['destination'], basename), env) + outputs += self.ninja.build(dst, 'copy', src, order_only=prebuild) + if self.is_mac_bundle: + # gyp has mac_bundle_resources to copy things into a bundle's + # Resources folder, but there's no built-in way to copy files to other + # places in the bundle. Hence, some targets use copies for this. Check + # if this file is copied into the current bundle, and if so add it to + # the bundle depends so that dependent targets get rebuilt if the copy + # input changes. + if dst.startswith(self.xcode_settings.GetBundleContentsFolderPath()): + mac_bundle_depends.append(dst) + + return outputs + + def _WriteIOSFrameworkHeaders(self, spec, outputs, prebuild): + """Prebuild steps to generate hmap files and copy headers to destination.""" + framework = self._ComputeMacBundleOutput() + all_sources = spec['sources'] + copy_headers = spec['mac_framework_headers'] + output = self._GypPathToUniqueOutput('headers.hmap') + self.xcode_settings.header_map_path = output + all_headers = map(self._GypPathToNinja, filter(lambda x: x.endswith('.h'), all_sources)) + variables = [('framework', framework), ('copy_headers', map(self._GypPathToNinja, copy_headers))] + outputs.extend(self.ninja.build(output, 'compile_ios_framework_headers', all_headers, variables=variables, order_only=prebuild)) + + def _WriteMacBundleResources(self, resources, bundle_depends): + """Writes ninja edges for 'mac_bundle_resources'.""" + xcassets = [] + + extra_env = self.xcode_settings.GetPerTargetSettings() + env = self._GetSortedXcodeEnv(additional_settings=extra_env) + env = self._ComputeExportEnvString(env) + isBinary = self.xcode_settings.IsBinaryOutputFormat(self.config_name) + + for output, res in gyp.xcode_emulation.GetMacBundleResources(generator_default_variables['PRODUCT_DIR'], self.xcode_settings, map(self._GypPathToNinja, resources)): + output = self._ExpandSpecial(output) + if os.path.splitext(output)[-1] != '.xcassets': + self.ninja.build(output, 'mac_tool', res, variables=[('mactool_cmd', 'copy-bundle-resource'), ('env', env), ('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 image-set 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.items(): + 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 = [os.path.join(self.xcode_settings.GetBundleResourceFolder(), 'Assets.car')] + if partial_info_plist: + outputs.append(partial_info_plist) + + keys = self._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, 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'], self.xcode_settings, self._GypPathToNinja) + if not info_plist: + return + out = self._ExpandSpecial(out) + if defines: + # Create an intermediate file to store preprocessed results. + intermediate_plist = self._GypPathToUniqueOutput(os.path.basename(info_plist)) + defines = ' '.join([self._Define(d, self.flavor) for d in 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) + + 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 = self._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, config_name, config, sources, pre_depends, precompiled_header, spec): + """Write build rules to compile all of |sources|.""" + if self.toolset == 'host': + self.ninja.variable('ar', '$ar_host') + self.ninja.variable('cc', '$cc_host') + 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(self.ninja, config_name, config, sources, pre_depends, precompiled_header, spec) + else: + return OrderedDict( + (arch, self._WriteSourcesForArch(self.arch_subninjas[arch], config_name, config, sources, pre_depends, precompiled_header, spec, arch=arch)) + for arch in self.archs + ) + + def _WriteSourcesForArch(self, ninja_file, config_name, config, sources, pre_depends, precompiled_header, spec, arch=None): + """Write build rules to compile all of |sources|.""" + + extra_defines = [] + asmflags = '' + cflags_objc = '' + cflags_objcc = '' + if self.flavor == 'mac': + cflags = self.xcode_settings.GetCflags(config_name, arch=arch) + cflags_c = self.xcode_settings.GetCflagsC(config_name) + cflags_cc = self.xcode_settings.GetCflagsCC(config_name) + cflags_objc = ['$cflags_c'] + self.xcode_settings.GetCflagsObjC(config_name) + 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) + # 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_c: + obj = 'obj' + if self.toolset != 'target': + obj += '.' + self.toolset + 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', []) + cflags_c = config.get('cflags_c', []) + cflags_cc = config.get('cflags_cc', []) + + # Respect environment variables related to build, but target-specific + # flags can still override them. + if self.toolset == 'target': + cflags_c = (os.environ.get('CPPFLAGS', '').split() + os.environ.get('CFLAGS', '').split() + cflags_c) + cflags_cc = (os.environ.get('CPPFLAGS', '').split() + os.environ.get('CXXFLAGS', '').split() + cflags_cc) + elif self.toolset == 'host': + cflags_c = (os.environ.get('CPPFLAGS_host', '').split() + os.environ.get('CFLAGS_host', '').split() + cflags_c) + cflags_cc = (os.environ.get('CPPFLAGS_host', '').split() + os.environ.get('CXXFLAGS_host', '').split() + cflags_cc) + + defines = config.get('defines', []) + extra_defines + self._WriteVariableList(ninja_file, 'defines', [self._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', [self._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) + self._WriteVariableList(ninja_file, 'includes', [self._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', [self._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. + for ext, var in [('c', 'cflags_pch_c'), ('cc', 'cflags_pch_cc'), ('m', 'cflags_pch_objc'), ('mm', 'cflags_pch_objcc')]: + 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', map(self._ExpandSpecial, cflags_c)) + self._WriteVariableList(ninja_file, 'cflags_cc', map(self._ExpandSpecial, cflags_cc)) + if self.flavor == 'mac': + self._WriteVariableList(ninja_file, 'cflags_objc', 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:] + obj_ext = self.obj_ext + if ext in ('cc', 'cpp', 'cxx'): + command = 'cxx' + self.target.uses_cpp = True + elif ext == 'c' or (ext == 'S' and self.flavor != 'win'): + command = 'cc' + elif ext == 's' and self.flavor != 'win': # Doesn't generate .o.d files. + command = 'cc_s' + elif self.flavor == 'win' and ext == 'asm' and not self.msvs_settings.HasExplicitAsmRules(spec): + command = 'asm' + # Add the _asm suffix as msvs is capable of handling .cc and + # .asm files of the same name without collision. + obj_ext = '_asm.obj' + elif self.flavor == 'mac' and ext == 'm': + command = 'objc' + elif self.flavor == 'mac' and ext == 'mm': + command = 'objcxx' + self.target.uses_cpp = True + elif self.flavor == 'win' and ext == 'rc': + command = 'rc' + obj_ext = '.res' + has_rc_source = True + else: + # Ignore unhandled extensions. + continue + inpt = self._GypPathToNinja(source) + otpt = self._GypPathToUniqueOutput(filename + obj_ext) + if arch is not None: + otpt = self._AddArch(otpt, arch) + implicit = precompiled_header.GetObjDependencies([inpt], [otpt], arch) + variables = [] + if self.flavor == 'win': + variables, otpt, implicit = precompiled_header.GetFlagsModifications(inpt, otpt, implicit, command, cflags_c, cflags_cc, self._ExpandSpecial) + ninja_file.build(otpt, command, inpt, implicit=[gch for _, _, gch in implicit], order_only=pre_depends, variables=variables) + outputs.append(otpt) + + if has_rc_source: + resource_include_dirs = config.get('resource_include_dirs', include_dirs) + self._WriteVariableList(ninja_file, 'resource_includes', [self._QuoteShellArgument('-I' + self._GypPathToNinja(i, env), self.flavor) for i in resource_include_dirs]) + + self._WritePchTargets(ninja_file, pch_commands) + + ninja_file.newline() + return outputs + + @staticmethod + def _WritePchTargets(ninja_file, pch_commands): + """Writes ninja rules to compile prefix headers.""" + if not pch_commands: + return + + for gch, lang_flag, lang, inpt in pch_commands: + var_name = { + 'c': 'cflags_pch_c', + 'cc': 'cflags_pch_cc', + 'm': 'cflags_pch_objc', + 'mm': 'cflags_pch_objcc', + }[lang] + + lang_map = {'c': 'cc', 'cc': 'cxx', 'm': 'objc', 'mm': 'objcxx', } + cmd = lang_map.get(lang) + ninja_file.build(gch, cmd, inpt, variables=[(var_name, lang_flag)]) + + def _WriteLink(self, spec, config_name, config, link_deps, compile_deps): + """Write out a link step. Fills out target.binary. """ + if self.flavor != 'mac' or len(self.archs) == 1: + return self._WriteLinkForArch(self.ninja, spec, config_name, config, link_deps, compile_deps) + else: + output = self._ComputeOutput(spec) + inputs = [self._WriteLinkForArch(self.arch_subninjas[arch], spec, config_name, config, link_deps[arch], compile_deps, 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) + + # 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, link_deps, compile_deps, arch=None): + """Write out a link step. Fills out target.binary. """ + command = { + 'executable': 'link', + 'loadable_module': 'solink_module', + 'shared_library': 'solink', + }[spec['type']] + command_suffix = '' + + implicit_deps = set() + solibs = set() + order_deps = set() + + if compile_deps: + # Normally, the compiles of the target already depend on compile_deps, + # but a shared_library target might have no sources and only link together + # a few static_library deps, so the link step also needs to depend + # on compile_deps to make sure actions in the shared_library target + # get run before the link. + order_deps.add(compile_deps) + + if 'dependencies' in spec: + # Two kinds of dependencies: + # - Linkable dependencies (like a .a or a .so): add them to the link line. + # - Non-linkable dependencies (like a rule that generates a file + # and writes a stamp file): add them to implicit_deps + extra_link_deps = set() + for dep in spec['dependencies']: + target = self.target_outputs.get(dep) + if not target: + continue + linkable = target.Linkable() + if linkable: + new_deps = [] + if self.flavor == 'win' and target.component_objs and self.msvs_settings.IsUseLibraryDependencyInputs(config_name): + new_deps = target.component_objs + if target.compile_deps: + order_deps.add(target.compile_deps) + elif self.flavor == 'win' and target.import_lib: + new_deps = [target.import_lib] + elif target.UsesToc(self.flavor): + solibs.add(target.binary) + implicit_deps.add(target.binary + '.TOC') + else: + 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) + + extra_bindings = [] + if self.target.uses_cpp and self.flavor != 'win': + extra_bindings.append(('ld', '$ldxx')) + + output = self._ComputeOutput(spec, arch) + if arch is None and not self.is_mac_bundle: + 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. + if self.toolset == 'target': + env_ldflags = os.environ.get('LDFLAGS', '').split() + else: # self.toolset == 'host' + env_ldflags = os.environ.get('LDFLAGS_host', '').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_base_name = self._GypPathToUniqueOutput(self.ComputeOutputFileName(spec)) + 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)) + 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 = env_ldflags + config.get('ldflags', []) + if is_executable and len(solibs): + rpath = 'lib/' + if self.toolset != 'target': + rpath += self.toolset + ldflags.append(r'-Wl,-rpath=\$$ORIGIN/%s' % rpath) + else: + ldflags.append('-Wl,-rpath=%s' % self.target_rpath) + ldflags.append('-Wl,-rpath-link=%s' % rpath) + self._WriteVariableList(ninja_file, '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 = ['/LIBPATH:' + self._QuoteShellArgument(self._GypPathToNinja(l), self.flavor) for l in library_dirs] + else: + library_dirs = [self._QuoteShellArgument('-L' + self._GypPathToNinja(l), self.flavor) for l in library_dirs] + + libraries = gyp.common.uniquer(map(self._ExpandSpecial, spec.get('libraries', []))) + if self.flavor == 'mac': + libraries = self.xcode_settings.AdjustLibraries(libraries, config_name) + elif self.flavor == 'win': + libraries = self.msvs_settings.AdjustLibraries(libraries) + + self._WriteVariableList(ninja_file, 'libs', library_dirs + libraries) + + linked_binary = output + + if command in ('solink', 'solink_module'): + 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(('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(sorted(solibs)))) + + ninja_file.build(output, command + command_suffix, link_deps, implicit=sorted(implicit_deps), order_only=list(order_deps), variables=extra_bindings) + return linked_binary + + def _WriteTarget(self, spec, config_name, config, link_deps, compile_deps): + extra_link_deps = any(self.target_outputs.get(dep).Linkable() for dep in spec.get('dependencies', []) if dep in self.target_outputs) + if spec['type'] == 'none' or (not link_deps and not extra_link_deps): + # TODO(evan): don't call this function for 'none' target types, as + # it doesn't do anything, and we fake out a 'binary' with a stamp file. + self.target.binary = compile_deps + self.target.type = 'none' + elif spec['type'] == 'static_library': + self.target.binary = self._ComputeOutput(spec) + if self.flavor not in ('mac', 'openbsd', 'netbsd', 'win') and not self.is_standalone_static_library: + self.ninja.build(self.target.binary, 'alink_thin', link_deps, order_only=compile_deps) + else: + variables = [] + if self.xcode_settings: + libtool_flags = self.xcode_settings.GetLibtoolflags(config_name) + if libtool_flags: + variables.append(('libtool_flags', libtool_flags)) + if self.msvs_settings: + libflags = self.msvs_settings.GetLibFlags(config_name, self._GypPathToNinja) + variables.append(('libflags', libflags)) + + if self.flavor != 'mac' or len(self.archs) == 1: + self._AppendPostbuildVariable(variables, spec, self.target.binary, self.target.binary) + self.ninja.build(self.target.binary, 'alink', link_deps, order_only=compile_deps, variables=variables) + else: + inputs = [] + for arch in self.archs: + output = self._ComputeOutput(spec, arch) + self.arch_subninjas[arch].build(output, 'alink', link_deps[arch], order_only=compile_deps, variables=variables) + inputs.append(output) + # TODO: It's not clear if libtool_flags should be passed to the alink + # call that combines single-arch .a files into a fat .a file. + self._AppendPostbuildVariable(variables, spec, self.target.binary, self.target.binary) + self.ninja.build(self.target.binary, 'alink', inputs, + # FIXME: test proving order_only=compile_deps isn't needed. + variables=variables) + else: + self.target.binary = self._WriteLink(spec, config_name, config, link_deps, compile_deps) + return self.target.binary + + def _WriteMacBundle(self, spec, mac_bundle_depends, is_empty): + assert self.is_mac_bundle + package_framework = spec['type'] in ('shared_library', 'loadable_module') + output = self._ComputeMacBundleOutput() + if is_empty: + output += '.stamp' + variables = [] + self._AppendPostbuildVariable(variables, spec, output, self.target.binary, is_command_start=not package_framework) + if package_framework and not is_empty: + if spec['type'] == 'shared_library' and self.xcode_settings.isIOS: + self.ninja.build(output, 'package_ios_framework', mac_bundle_depends, variables=variables) + else: + variables.append(('version', self.xcode_settings.GetFrameworkVersion())) + self.ninja.build(output, 'package_framework', mac_bundle_depends, variables=variables) + else: + self.ninja.build(output, 'stamp', mac_bundle_depends, variables=variables) + 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.msvs_settings.GetVSMacroEnv('$!PRODUCT_DIR', config=self.config_name) + return env + + def _GetSortedXcodeEnv(self, additional_settings=None): + """Returns the variables Xcode would set for build steps.""" + assert self.abs_build_dir + path = os.path.join(self.abs_build_dir, self.build_to_base) + return gyp.xcode_emulation.GetSortedXcodeEnv(self.xcode_settings, self.abs_build_dir, path, self.config_name, additional_settings) + + def _GetSortedXcodePostbuildEnv(self): + """Returns the variables Xcode would set for postbuild steps.""" + postbuild_settings = {} + # CHROMIUM_STRIP_SAVE_FILE is a chromium-specific hack. + # TODO(thakis): It would be nice to have some general mechanism instead. + strip_save_file = self.xcode_settings.GetPerTargetSetting('CHROMIUM_STRIP_SAVE_FILE') + if strip_save_file: + postbuild_settings['CHROMIUM_STRIP_SAVE_FILE'] = strip_save_file + return self._GetSortedXcodeEnv(additional_settings=postbuild_settings) + + def _AppendPostbuildVariable(self, variables, spec, output, binary, is_command_start=False): + """Adds a 'postbuild' variable if there is a postbuild for |output|.""" + postbuild = self._GetPostbuildCommand(spec, output, binary, is_command_start) + if postbuild: + variables.append(('postbuilds', postbuild)) + + def _GetPostbuildCommand(self, spec, output, output_binary, is_command_start): + """Returns a shell command that runs all the postbuilds, and removes + |output| if any of them fails. If |is_command_start| is False, then the + returned string will start with ' && '.""" + if not self.xcode_settings or spec['type'] == 'none' or not output: + return '' + output = self._QuoteShellArgument(output, self.flavor) + postbuilds = gyp.xcode_emulation.GetSpecPostbuildCommands(spec, quiet=True) + if output_binary is not None: + output_path = os.path.normpath(os.path.join(self.base_to_build, output)) + output_binary_path = self._QuoteShellArgument(os.path.normpath(os.path.join(self.base_to_build, output_binary)), self.flavor) + postbuilds = self.xcode_settings.AddImplicitPostbuilds(self.config_name, output_path, output_binary_path, postbuilds, quiet=True) + + if not postbuilds: + return '' + # Postbuilds expect to be run in the gyp file's directory, so insert an + # implicit postbuild to cd to there. + postbuilds.insert(0, gyp.common.EncodePOSIXShellList(['cd', self.build_to_base])) + env = self._ComputeExportEnvString(self._GetSortedXcodePostbuildEnv()) + # G will be non-null if any postbuild fails. Run all postbuilds in a + # subshell. + commands = env + ' (' + ' && '.join([ninja_syntax.escape(command) for command in postbuilds]) + command_string = (commands + '); G=$$?; ' + # Remove the final output if any postbuild failed. + '((exit $$G) || rm -rf %s) ' % output + '&& exit $$G)') + if is_command_start: + return '(' + command_string + ' && ' + else: + return '$ && (' + command_string + + @staticmethod + def _ComputeExportEnvString(env): + """Given an environment, returns a string looking like + 'export FOO=foo; export BAR="${FOO} bar;' + that exports |env| to the shell.""" + export_str = [] + for k, v in env: + export_str.append('export %s=%s;' % (k, ninja_syntax.escape(gyp.common.EncodePOSIXShellArgument(v)))) + return ' '.join(export_str) + + def _ComputeMacBundleOutput(self): + """Return the 'output' (full output path) to a bundle output directory.""" + assert self.is_mac_bundle + path = generator_default_variables['PRODUCT_DIR'] + return self._ExpandSpecial(os.path.join(path, self.xcode_settings.GetWrapperName())) + + def _ComputeOutput(self, spec, arch=None): + """Compute the path for the final output of the spec.""" + typ = spec['type'] + + if self.flavor == 'win': + override = self.msvs_settings.GetOutputName(self.config_name, self._ExpandSpecial) + if override: + return override + + if arch is None and self.flavor == 'mac' and typ in ( + 'static_library', 'executable', 'shared_library', 'loadable_module'): + filename = self.xcode_settings.GetExecutablePath() + else: + filename = self.ComputeOutputFileName(spec, typ) + + if arch is None and 'product_dir' in spec: + path = os.path.join(spec['product_dir'], filename) + return self._ExpandSpecial(path) + + # Some products go into the output root, libraries go into shared library + # dir, and everything else goes into the normal place. + type_in_output_root = ['executable', 'loadable_module'] + if self.flavor == 'mac' and self.toolset == 'target': + type_in_output_root += ['shared_library', 'static_library'] + elif self.flavor == 'win' and self.toolset == 'target': + type_in_output_root += ['shared_library'] + + if arch is not None: + # Make sure partial executables don't end up in a bundle or the regular + # output directory. + archdir = 'arch' + if self.toolset != 'target': + archdir = os.path.join('arch', '%s' % self.toolset) + return os.path.join(archdir, self._AddArch(filename, arch)) + elif typ in type_in_output_root or self.is_standalone_static_library: + return filename + elif typ == 'shared_library': + libdir = 'lib' + if self.toolset != 'target': + libdir = os.path.join('lib', '%s' % self.toolset) + return os.path.join(libdir, filename) + else: + return self._GypPathToUniqueOutput(filename, qualified=False) + + @staticmethod + def _WriteVariableList(ninja_file, var, values): + assert not isinstance(values, str) + if values is None: + values = [] + ninja_file.variable(var, ' '.join(values)) + + 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 + expanded.""" + + if self.flavor == 'win': + args = [self.msvs_settings.ConvertVSMacros(arg, self.base_to_build, config=self.config_name) for arg in args] + description = self.msvs_settings.ConvertVSMacros(description, config=self.config_name) + elif self.flavor == 'mac': + # |env| is an empty list on non-mac. + args = [gyp.xcode_emulation.ExpandEnvVars(arg, env) for arg in args] + description = gyp.xcode_emulation.ExpandEnvVars(description, env) + + # TODO: we shouldn't need to qualify names; we do it because + # currently the ninja rule namespace is global, but it really + # should be scoped to the subninja. + rule_name = self.name + if self.toolset == 'target': + rule_name += '.' + self.toolset + rule_name += '.' + name + rule_name = re.sub('[^a-zA-Z0-9_]', '_', rule_name) + + # Remove variable references, but not if they refer to the magic rule + # variables. This is not quite right, as it also protects these for + # actions, not just for rules where they are valid. Good enough. + protect = ['${root}', '${dirname}', '${source}', '${ext}', '${name}'] + protect = '(?!' + '|'.join(map(re.escape, protect)) + ')' + description = re.sub(protect + r'\$', '_', description) + + # gyp dictates that commands are run from the base directory. + # cd into the directory before running, and adjust paths in + # the arguments to point to the proper locations. + rspfile = None + rspfile_content = None + args = [self._ExpandSpecial(arg, self.base_to_build) for arg in args] + if self.flavor == 'win': + rspfile = rule_name + '.$unique_name.rsp' + # The cygwin case handles this inside the bash sub-shell. + run_in = '' if is_cygwin else ' ' + self.build_to_base + if is_cygwin: + rspfile_content = self.msvs_settings.BuildCygwinBashCommandLine(args, self.build_to_base) + else: + rspfile_content = gyp.msvs_emulation.EncodeRspFileList(args) + command = ('%s gyp-win-tool action-wrapper $arch ' % sys.executable + rspfile + run_in) + else: + env = self._ComputeExportEnvString(env) + command = gyp.common.EncodePOSIXShellList(args) + command = 'cd %s; ' % self.build_to_base + env + command + + # 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, depfile=depfile, restat=True, pool=pool, rspfile=rspfile, rspfile_content=rspfile_content) + self.ninja.newline() + + return rule_name, args + + def ComputeOutputFileName(self, spec, typ=None): + """Compute the filename of the final output for the current target.""" + if not typ: + typ = spec['type'] + + default_variables = copy.copy(generator_default_variables) + CalculateVariables(default_variables, {'flavor': self.flavor}) + + # Compute filename prefix: the product prefix, or a default for + # the product type. + DEFAULT_PREFIX = { + 'loadable_module': default_variables['SHARED_LIB_PREFIX'], + 'shared_library': default_variables['SHARED_LIB_PREFIX'], + 'static_library': default_variables['STATIC_LIB_PREFIX'], + 'executable': default_variables['EXECUTABLE_PREFIX'], + } + prefix = spec.get('product_prefix', DEFAULT_PREFIX.get(typ, '')) + + # Compute filename extension: the product extension, or a default + # for the product type. + DEFAULT_EXTENSION = { + 'loadable_module': default_variables['SHARED_LIB_SUFFIX'], + 'shared_library': default_variables['SHARED_LIB_SUFFIX'], + 'static_library': default_variables['STATIC_LIB_SUFFIX'], + 'executable': default_variables['EXECUTABLE_SUFFIX'], + } + extension = spec.get('product_extension') + if extension: + extension = '.' + extension + else: + extension = DEFAULT_EXTENSION.get(typ, '') + + if 'product_name' in spec: + # If we were given an explicit name, use that. + target = spec['product_name'] + else: + # Otherwise, derive a name from the target name. + target = spec['target_name'] + if prefix == 'lib': + # Snip out an extra 'lib' from libs if appropriate. + target = self._StripPrefix(target, 'lib') + + if typ in ('static_library', 'loadable_module', 'shared_library', 'executable'): + return '%s%s%s' % (prefix, target, extension) + elif typ == 'none': + return '%s.stamp' % target + else: + raise Exception('Unhandled output type %s' % typ) + + def WriteSpec(self): + """ + The entry point for NinjaWriter: write the build rules for a spec. + + Returns a Target object, which represents the output paths for this spec. + Returns None if there are no outputs (e.g. a settings-only 'none' type + target). + """ + + if self.flavor == 'mac': + self.xcode_settings = xcode_emulation.XcodeSettings(self.spec) + mac_toolchain_dir = self.generator_flags.get('mac_toolchain_dir', None) + if mac_toolchain_dir: + self.xcode_settings.mac_toolchain_dir = mac_toolchain_dir + + if self.flavor == 'win': + self.msvs_settings = msvs_emulation.MsvsSettings(self.spec, self.generator_flags) + arch = self.msvs_settings.GetArch(self.config_name) + 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(self.config_name) + if len(self.archs) > 1: + self.arch_subninjas = dict( + (arch, ninja_syntax.Writer(OpenOutput(os.path.join(self.toplevel_build, self._SubninjaNameForArch(arch))))) + for arch in self.archs + ) + + # Compute pre-depends for all rules. + # actions_depends is the dependencies this target depends on before running any of its action/rule/copy steps. + # compile_depends is the dependencies this target depends on before running any of its compile steps. + actions_depends = [] + compile_depends = [] + # TODO(evan): it is rather confusing which things are lists and which + # are strings. Fix these. + if 'dependencies' in self.spec: + for dep in self.spec['dependencies']: + if dep in self.target_outputs: + target = self.target_outputs[dep] + actions_depends.append(target.PreActionInput(self.flavor)) + compile_depends.append(target.PreCompileInput()) + if target.uses_cpp: + self.target.uses_cpp = True + actions_depends = [d for d in actions_depends if d] + compile_depends = [d for d in compile_depends if d] + actions_depends = self._WriteCollapsedDependencies('actions_depends', actions_depends) + compile_depends = self._WriteCollapsedDependencies('compile_depends', compile_depends) + self.target.preaction_stamp = actions_depends + self.target.precompile_stamp = compile_depends + + # Write out actions, rules, and copies. These must happen before we + # compile any sources, so compute a list of predependencies for sources + # while we do it. + extra_sources = [] + mac_bundle_depends = [] + self.target.actions_stamp = self._WriteActionsRulesCopies(self.spec, extra_sources, actions_depends, mac_bundle_depends) + + # If we have actions/rules/copies, we depend directly on those, but + # otherwise we depend on dependent target's actions/rules/copies etc. + # We never need to explicitly depend on previous target's link steps, + # because no compile ever depends on them. + compile_depends_stamp = self.target.actions_stamp or compile_depends + + # Write out the compilation steps, if any. + link_deps = [] + try: + sources = extra_sources + self.spec.get('sources', []) + except TypeError: + print('extra_sources: ', str(extra_sources)) + print('spec.get("sources"): ', str(self.spec.get('sources'))) + raise + if sources: + if self.flavor == 'mac' and len(self.archs) > 1: + # Write subninja file containing compile and link commands scoped to + # a single arch if a fat binary is being built. + for arch in self.archs: + self.ninja.subninja(self._SubninjaNameForArch(arch)) + + if self.flavor == 'win': + gyp.msvs_emulation.VerifyMissingSources(sources, self.abs_build_dir, self.generator_flags, self._GypPathToNinja) + pch = gyp.msvs_emulation.PrecompiledHeader(self.msvs_settings, self.config_name, self._GypPathToNinja, self._GypPathToUniqueOutput, self.obj_ext) + else: + pch = gyp.xcode_emulation.MacPrefixHeader(self.xcode_settings, self._GypPathToNinja, lambda path, lang: self._GypPathToUniqueOutput(path + '-' + lang)) + link_deps = self._WriteSources(self.config_name, self.config, sources, compile_depends_stamp, pch, self.spec) + # Some actions/rules output 'sources' that are already object files. + obj_outputs = [f for f in sources if f.endswith(self.obj_ext)] + if obj_outputs: + if self.flavor != 'mac' or len(self.archs) == 1: + link_deps += [self._GypPathToNinja(o) for o in obj_outputs] + else: + print("Warning: Actions/rules writing object files don't work with multi-arch targets, dropping. (target %s)" % self.spec['target_name']) + elif self.flavor == 'mac' and len(self.archs) > 1: + link_deps = OrderedDict((a, []) for a in self.archs) + + compile_deps = self.target.actions_stamp or actions_depends + if self.flavor == 'win' and self.target.type == 'static_library': + self.target.component_objs = link_deps + self.target.compile_deps = compile_deps + + # Write out a link step, if needed. + output = None + is_empty_bundle = not link_deps and not mac_bundle_depends + if link_deps or self.target.actions_stamp or actions_depends: + output = self._WriteTarget(self.spec, self.config_name, self.config, link_deps, compile_deps) + if self.is_mac_bundle: + mac_bundle_depends.append(output) + + # Bundle all of the above together, if needed. + if self.is_mac_bundle: + output = self._WriteMacBundle(self.spec, mac_bundle_depends, is_empty_bundle) + + if not output: + return None + + assert self.target.FinalOutput(), output + return self.target + + + def _Define(self, d, flavor): + """Takes a preprocessor define and returns a -D parameter that's ninja- and + shell-escaped.""" + if flavor == 'win': + # cl.exe replaces literal # characters with = in preprocesor definitions for + # some reason. Octal-encode to work around that. + d = d.replace('#', '\\%03o' % ord('#')) + return self._QuoteShellArgument(ninja_syntax.escape('-D' + d), flavor) + + + @staticmethod + def _StripPrefix(arg, prefix): + if arg.startswith(prefix): + return arg[len(prefix):] + return arg + + + @staticmethod + def _QuoteShellArgument(arg, flavor): + """Quote a string such that it will be interpreted as a single argument + by the shell.""" + # Rather than attempting to enumerate the bad shell characters, just + # whitelist common OK ones and quote anything else. + if re.match(r'^[a-zA-Z0-9_=.\\/-]+$', arg): + return arg # No quoting necessary. + if flavor == 'win': + return gyp.msvs_emulation.QuoteForRspFile(arg) + return "'" + arg.replace("'", "'" + '"\'"' + "'") + "'" + + + @staticmethod + def _AddArch(output, arch): + """Adds an arch string to an output path.""" + output, extension = os.path.splitext(output) + return '%s.%s%s' % (output, arch, extension) diff --git a/tools/gyp/gyp/XCodeDetect.py b/tools/gyp/gyp/XCodeDetect.py new file mode 100644 index 00000000000000..cc7b8fac5abc89 --- /dev/null +++ b/tools/gyp/gyp/XCodeDetect.py @@ -0,0 +1,65 @@ +import subprocess +import sys + + +def run(*cmd_args): + return subprocess.check_output(cmd_args, stderr=subprocess.PIPE).decode('utf-8') + + +class XCodeDetect(object): + """Simplify access to Xcode information.""" + _cache = {} + + @staticmethod + def Version(): + if 'Version' not in XCodeDetect._cache: + version = '' + try: + lines = run('xcodebuild', '-version').splitlines() + version = ''.join(lines[0].decode('utf-8').split()[-1].split('.')) + version = (version + '0' * (3 - len(version))).zfill(4) + except subprocess.CalledProcessError: + pass + try: + lines = run('pkgutil', '--pkg-info=com.apple.pkg.CLTools_Executables').splitlines() + for l in lines: + n, v = l.split(': ', 1) + if n != 'version': + continue + parts = v.split('.',4) + version = '%s%s%s%s' % tuple(parts[0:4]) + break + except subprocess.CalledProcessError: + pass + XCodeDetect._cache['Version'] = version + return XCodeDetect._cache['Version'] + + + @staticmethod + def SDKVersion(): + if 'SDKVersion' not in XCodeDetect._cache: + out = '' + try: + out = run('xcrun', '--show-sdk-version') + except subprocess.CalledProcessError: + pass + try: + out = run('xcodebuild', '-version', '-sdk', '', 'SDKVersion') + except subprocess.CalledProcessError: + pass + XCodeDetect._cache['SDKVersion'] = out.strip() + return XCodeDetect._cache['SDKVersion'] + + + @staticmethod + def HasIPhoneSDK(): + if not sys.platform == 'darwin': + return False + + if 'HasIPhoneSDK' not in XCodeDetect._cache: + try: + out = run('xcrun', '--sdk', 'iphoneos', '--show-sdk-path') + except subprocess.CalledProcessError: + out = 1 + XCodeDetect._cache['HasIPhoneSDK'] = out == 0 + return XCodeDetect._cache['HasIPhoneSDK'] diff --git a/tools/gyp/pylib/gyp/__init__.py b/tools/gyp/gyp/__init__.py old mode 100755 new mode 100644 similarity index 66% rename from tools/gyp/pylib/gyp/__init__.py rename to tools/gyp/gyp/__init__.py index 668f38b60d0093..68e047f7dde897 --- a/tools/gyp/pylib/gyp/__init__.py +++ b/tools/gyp/gyp/__init__.py @@ -4,6 +4,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +from __future__ import print_function + import copy import gyp.input import optparse @@ -12,8 +14,12 @@ import shlex import sys import traceback +from collections import OrderedDict from gyp.common import GypError +if not 'basestring' in __builtins__: + basestring = str + # Default debug modes for GYP debug = {} @@ -34,8 +40,8 @@ def DebugOutput(mode, message, *args): pass if args: message %= args - print '%s:%s:%d:%s %s' % (mode.upper(), os.path.basename(ctx[0]), - ctx[1], ctx[2], message) + print('%s:%s:%d:%s %s' % (mode.upper(), os.path.basename(ctx[0]), ctx[1], ctx[2], message)) + def FindBuildFiles(): extension = '.gyp' @@ -47,33 +53,28 @@ def FindBuildFiles(): return build_files -def Load(build_files, format, default_variables={}, - includes=[], depth='.', params=None, check=False, - circular_check=True, duplicate_basename_check=True): +def Load(build_files, output_format, default_variables, includes, params, depth): """ Loads one or more specified build files. default_variables and includes will be copied before use. - Returns the generator for the specified format and the + Returns the generator for the specified output_format and the data returned by loading the specified build files. """ - if params is None: - params = {} - - if '-' in format: - format, params['flavor'] = format.split('-', 1) + if '-' in output_format: + output_format, params['flavor'] = output_format.split('-', 1) default_variables = copy.copy(default_variables) # Default variables provided by this program and its modules should be # 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'] = output_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. - if format.endswith('.py'): - generator_name = os.path.splitext(format)[0] + if output_format.endswith('.py'): + generator_name = os.path.splitext(output_format)[0] path, generator_name = os.path.split(generator_name) # Make sure the path to the custom generator is in sys.path @@ -84,7 +85,7 @@ def Load(build_files, format, default_variables={}, if path not in sys.path: sys.path.insert(0, path) else: - generator_name = 'gyp.generator.' + format + generator_name = 'gyp.generator.' + output_format # These parameters are passed in order (as opposed to by key) # because ActivePython cannot handle key parameters to __import__. @@ -94,49 +95,39 @@ def Load(build_files, format, default_variables={}, # Give the generator the opportunity to set additional variables based on # the params it will receive in the output phase. - if getattr(generator, 'CalculateVariables', None): + if hasattr(generator, 'CalculateVariables'): generator.CalculateVariables(default_variables, params) # Give the generator the opportunity to set generator_input_info based on # the params it will receive in the output phase. - if getattr(generator, 'CalculateGeneratorInputInfo', None): + if hasattr(generator, 'CalculateGeneratorInputInfo'): generator.CalculateGeneratorInputInfo(params) # Fetch the generator specific info that gets fed to input, we use getattr # so we can default things and the generators only have to provide what # they need. generator_input_info = { - 'non_configuration_keys': - getattr(generator, 'generator_additional_non_configuration_keys', []), - 'path_sections': - getattr(generator, 'generator_additional_path_sections', []), - 'extra_sources_for_rules': - getattr(generator, 'generator_extra_sources_for_rules', []), - 'generator_supports_multiple_toolsets': - getattr(generator, 'generator_supports_multiple_toolsets', False), - 'generator_wants_static_library_dependencies_adjusted': - getattr(generator, - '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), + 'non_configuration_keys': getattr(generator, 'generator_additional_non_configuration_keys', []), + 'path_sections': getattr(generator, 'generator_additional_path_sections', []), + 'extra_sources_for_rules': getattr(generator, 'generator_extra_sources_for_rules', []), + 'generator_supports_multiple_toolsets': getattr(generator, 'generator_supports_multiple_toolsets', False), + 'generator_wants_static_library_dependencies_adjusted': getattr(generator, '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, - duplicate_basename_check, - params['parallel'], params['root_targets']) + result = gyp.input.Load(build_files, default_variables, includes[:], depth, generator_input_info, params['root_targets']) return [generator] + result + def NameValueListToDict(name_value_list): """ Takes an array of strings of the form 'NAME=VALUE' and creates a dictionary of the pairs. If a string is simply NAME, then the value in the dictionary is set to True. If VALUE can be converted to an integer, it is. """ - result = { } + result = OrderedDict() for item in name_value_list: tokens = item.split('=', 1) if len(tokens) == 2: @@ -152,17 +143,20 @@ def NameValueListToDict(name_value_list): result[tokens[0]] = True return result + def ShlexEnv(env_name): flags = os.environ.get(env_name, []) if flags: flags = shlex.split(flags) return flags + def FormatOpt(opt, value): if opt.startswith('--'): return '%s=%s' % (opt, value) return opt + value + def RegenerateAppendFlag(flag, values, predicate, env_name, options): """Regenerate a list of command line flags, for an option of action='append'. @@ -185,6 +179,7 @@ def RegenerateAppendFlag(flag, values, predicate, env_name, options): flags.append(FormatOpt(flag, predicate(flag_value))) return flags + def RegenerateFlags(options): """Given a parsed options object, and taking the environment variables into account, returns a list of flags that should regenerate an equivalent options @@ -195,6 +190,7 @@ def RegenerateFlags(options): The format flag is not included, as it is assumed the calling generator will set that as appropriate. """ + def FixPath(path): path = gyp.common.FixIfRelativePath(path, options.depth) if not path: @@ -207,34 +203,30 @@ def Noop(value): # We always want to ignore the environment when regenerating, to avoid # duplicate or changed flags in the environment at the time of regeneration. flags = ['--ignore-environment'] - for name, metadata in options._regeneration_metadata.iteritems(): + for name, metadata in options._regeneration_metadata.items(): opt = metadata['opt'] value = getattr(options, name) value_predicate = metadata['type'] == 'path' and FixPath or Noop action = metadata['action'] env_name = metadata['env_name'] if action == 'append': - flags.extend(RegenerateAppendFlag(opt, value, value_predicate, - env_name, options)) + flags.extend(RegenerateAppendFlag(opt, value, value_predicate, env_name, options)) elif action in ('store', None): # None is a synonym for 'store'. if value: flags.append(FormatOpt(opt, value_predicate(value))) elif options.use_environment and env_name and os.environ.get(env_name): flags.append(FormatOpt(opt, value_predicate(os.environ.get(env_name)))) elif action in ('store_true', 'store_false'): - if ((action == 'store_true' and value) or - (action == 'store_false' and not value)): + if ((action == 'store_true' and value) or (action == 'store_false' and not value)): flags.append(opt) elif options.use_environment and env_name: - print >>sys.stderr, ('Warning: environment regeneration unimplemented ' - 'for %s flag %r env_name %r' % (action, opt, - env_name)) + print('Warning: environment regeneration unimplemented for %s flag %r env_name %r' % (action, opt, env_name), file=sys.stderr) else: - print >>sys.stderr, ('Warning: regeneration unimplemented for action %r ' - 'flag %r' % (action, opt)) + print('Warning: regeneration unimplemented for action %r flag %r' % (action, opt), file=sys.stderr) return flags + class RegeneratableOptionParser(optparse.OptionParser): def __init__(self): self.__regeneratable_options = {} @@ -263,11 +255,11 @@ def add_option(self, *args, **kw): kw['type'] = 'string' self.__regeneratable_options[dest] = { - 'action': kw.get('action'), - 'type': type, - 'env_name': env_name, - 'opt': args[0], - } + 'action': kw.get('action'), + 'type': type, + 'env_name': env_name, + 'opt': args[0], + } optparse.OptionParser.add_option(self, *args, **kw) @@ -276,82 +268,35 @@ def parse_args(self, *args): values._regeneration_metadata = self.__regeneratable_options return values, args -def gyp_main(args): - my_name = os.path.basename(sys.argv[0]) +def gyp_main(args): parser = RegeneratableOptionParser() usage = 'usage: %s [options ...] [build_file ...]' parser.set_usage(usage.replace('%s', '%prog')) - parser.add_option('--build', dest='configs', action='append', - help='configuration for build after project generation') - parser.add_option('--check', dest='check', action='store_true', - help='check format of gyp files') - parser.add_option('--config-dir', dest='config_dir', action='store', - env_name='GYP_CONFIG_DIR', default=None, - help='The location for configuration files like ' - 'include.gypi.') - parser.add_option('-d', '--debug', dest='debug', metavar='DEBUGMODE', - action='append', default=[], help='turn on a debugging ' - 'mode for debugging GYP. Supported modes are "variables", ' - '"includes" and "general" or "all" for all of them.') - parser.add_option('-D', dest='defines', action='append', metavar='VAR=VAL', - env_name='GYP_DEFINES', - help='sets variable VAR to value VAL') - parser.add_option('--depth', dest='depth', metavar='PATH', type='path', - help='set DEPTH gyp variable to a relative path to PATH') - parser.add_option('-f', '--format', dest='formats', action='append', - env_name='GYP_GENERATORS', regenerate=False, - help='output formats to generate') - parser.add_option('-G', dest='generator_flags', action='append', default=[], - metavar='FLAG=VAL', env_name='GYP_GENERATOR_FLAGS', - help='sets generator flag FLAG to VAL') - parser.add_option('--generator-output', dest='generator_output', - action='store', default=None, metavar='DIR', type='path', - env_name='GYP_GENERATOR_OUTPUT', - help='puts generated build files under DIR') - parser.add_option('--ignore-environment', dest='use_environment', - action='store_false', default=True, regenerate=False, - help='do not read options from environment variables') - parser.add_option('-I', '--include', dest='includes', action='append', - metavar='INCLUDE', type='path', - help='files to include in all loaded .gyp files') - # --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 - # currently have some circular relationships on non-Mac platforms, so this - # option allows the strict behavior to be used on Macs and the lenient - # behavior to be used elsewhere. - # TODO(mark): Remove this option when http://crbug.com/35878 is fixed. - 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") - # --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') + parser.add_option('--build', dest='configs', action='append', help='configuration for build after project generation') + parser.add_option('--config-dir', dest='config_dir', action='store', env_name='GYP_CONFIG_DIR', default=None, help='The location for configuration files like include.gypi.') + parser.add_option('-d', '--debug', dest='debug', metavar='DEBUGMODE', action='append', default=[], help='turn on a debugging mode for debugging GYP. Supported modes are "variables", "includes" and "general" or "all" for all of them.') + parser.add_option('-D', dest='defines', action='append', metavar='VAR=VAL', env_name='GYP_DEFINES', help='sets variable VAR to value VAL') + parser.add_option('--depth', dest='depth', metavar='PATH', type='path', help='set DEPTH gyp variable to a relative path to PATH') + parser.add_option('-f', '--format', dest='formats', action='append', env_name='GYP_GENERATORS', regenerate=False, help='output formats to generate') + parser.add_option('-G', dest='generator_flags', action='append', default=[], metavar='FLAG=VAL', env_name='GYP_GENERATOR_FLAGS', help='sets generator flag FLAG to VAL') + parser.add_option('--generator-output', dest='generator_output', action='store', default=None, metavar='DIR', type='path', env_name='GYP_GENERATOR_OUTPUT', help='puts generated build files under DIR') + parser.add_option('--ignore-environment', dest='use_environment', action='store_false', default=True, regenerate=False, help='do not read options from environment variables') + 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('-R', '--root-target', dest='root_targets', action='append', metavar='TARGET', help='include only TARGET and its deep dependencies') + 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') + # TODO(refack) deprecated - Have no effect. Kept as to not break CLI usage + parser.add_option('--check', dest='check', action='store_true', help='check format of gyp files') + 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('--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') options, build_files_arg = parser.parse_args(args) build_files = build_files_arg # Set up the configuration directory (defaults to ~/.gyp) if not options.config_dir: - home = None home_dot_gyp = None if options.use_environment: home_dot_gyp = os.environ.get('GYP_CONFIG_DIR', None) @@ -364,7 +309,7 @@ def gyp_main(args): home_vars.append('USERPROFILE') for home_var in home_vars: home = os.getenv(home_var) - if home != None: + if home is not None: home_dot_gyp = os.path.join(home, '.gyp') if not os.path.exists(home_dot_gyp): home_dot_gyp = None @@ -377,7 +322,7 @@ def gyp_main(args): home_dot_gyp = None if not options.formats: - # If no format was given on the command line, then check the env variable. + # If no output_format was given on the command line, then check the env variable. generate_formats = [] if options.use_environment: generate_formats = os.environ.get('GYP_GENERATORS', []) @@ -399,8 +344,6 @@ def gyp_main(args): if g_o: options.generator_output = g_o - options.parallel = not options.no_parallel - for mode in options.debug: gyp.debug[mode] = 1 @@ -418,8 +361,8 @@ def gyp_main(args): if not build_files: build_files = FindBuildFiles() if not build_files: - raise GypError((usage + '\n\n%s: error: no build_file') % - (my_name, my_name)) + my_name = os.path.basename(sys.argv[0]) + raise GypError((usage + '\n\n%s: error: no build_file') % (my_name, my_name)) # TODO(mark): Chromium-specific hack! # For Chromium, the gyp "depth" variable should always be a relative path @@ -431,12 +374,11 @@ def gyp_main(args): for build_file in build_files: build_file_dir = os.path.abspath(os.path.dirname(build_file)) build_file_dir_components = build_file_dir.split(os.path.sep) - components_len = len(build_file_dir_components) - for index in xrange(components_len - 1, -1, -1): - if build_file_dir_components[index] == 'src': + for component in reversed(build_file_dir_components): + if component == 'src': options.depth = os.path.sep.join(build_file_dir_components) break - del build_file_dir_components[index] + del build_file_dir_components[-1] # If the inner loop found something, break without advancing to another # build file. @@ -456,7 +398,6 @@ def gyp_main(args): # -D on the command line sets variable defaults - D isn't just for define, # it's for default. Perhaps there should be a way to force (-F?) a # variable's value so that it can't be overridden by anything else. - cmdline_default_variables = {} defines = [] if options.use_environment: defines += ShlexEnv('GYP_DEFINES') @@ -464,18 +405,17 @@ def gyp_main(args): defines += options.defines cmdline_default_variables = NameValueListToDict(defines) if DEBUG_GENERAL in gyp.debug: - DebugOutput(DEBUG_GENERAL, - "cmdline_default_variables: %s", cmdline_default_variables) + DebugOutput(DEBUG_GENERAL, "cmdline_default_variables: %s", cmdline_default_variables) # Set up includes. includes = [] # If ~/.gyp/include.gypi exists, it'll be forcibly included into every # .gyp file that's loaded, before anything else is included. - if home_dot_gyp != None: + if home_dot_gyp is not None: default_include = os.path.join(home_dot_gyp, 'include.gypi') if os.path.exists(default_include): - print 'Using overrides found in ' + default_include + print('Using overrides found in ' + default_include) includes.append(default_include) # Command-line --include files come after the default include. @@ -490,28 +430,25 @@ def gyp_main(args): if options.generator_flags: gen_flags += options.generator_flags generator_flags = NameValueListToDict(gen_flags) - if DEBUG_GENERAL in gyp.debug.keys(): + if DEBUG_GENERAL in gyp.debug: DebugOutput(DEBUG_GENERAL, "generator_flags: %s", generator_flags) - # Generate all requested formats (use a set in case we got one format request - # twice) - for format in set(options.formats): - params = {'options': options, - 'build_files': build_files, - 'generator_flags': generator_flags, - 'cwd': os.getcwd(), - 'build_files_arg': build_files_arg, - 'gyp_binary': sys.argv[0], - 'home_dot_gyp': home_dot_gyp, - 'parallel': options.parallel, - 'root_targets': options.root_targets, - 'target_arch': cmdline_default_variables.get('target_arch', '')} + # Generate all requested formats (use a set in case we got one output_format request twice) + for output_format in set(options.formats): + params = { + 'options': options, + 'build_files': build_files, + 'generator_flags': generator_flags, + 'cwd': os.getcwd(), + 'build_files_arg': build_files_arg, + 'gyp_binary': sys.argv[0], + 'home_dot_gyp': home_dot_gyp, + '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, - options.duplicate_basename_check) + [generator, flat_list, targets, data] = Load(build_files, output_format, cmdline_default_variables, includes, params, options.depth) # 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 @@ -523,7 +460,7 @@ def gyp_main(args): generator.GenerateOutput(flat_list, targets, data, params) if options.configs: - valid_configs = targets[flat_list[0]]['configurations'].keys() + valid_configs = targets[flat_list[0]]['configurations'] for conf in options.configs: if conf not in valid_configs: raise GypError('Invalid config specified via --build: %s' % conf) @@ -536,13 +473,15 @@ def gyp_main(args): def main(args): try: return gyp_main(args) - except GypError, e: + except GypError as e: sys.stderr.write("gyp: %s\n" % e) return 1 + # NOTE: setuptools generated console_scripts calls function with no arguments def script_main(): return main(sys.argv[1:]) + if __name__ == '__main__': sys.exit(script_main()) diff --git a/tools/gyp/pylib/gyp/flock_tool.py b/tools/gyp/gyp/buildtime_helpers/flock_tool.py old mode 100755 new mode 100644 similarity index 79% rename from tools/gyp/pylib/gyp/flock_tool.py rename to tools/gyp/gyp/buildtime_helpers/flock_tool.py index b38d8660f72853..edc4b074306f69 --- a/tools/gyp/pylib/gyp/flock_tool.py +++ b/tools/gyp/gyp/buildtime_helpers/flock_tool.py @@ -6,6 +6,7 @@ """These functions are executed via gyp-flock-tool when using the Makefile generator. Used on systems that don't have a built-in flock.""" +# noinspection PyUnresolvedReferences import fcntl import os import struct @@ -33,13 +34,15 @@ def _CommandifyName(self, name_string): 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) + """ + 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. + """ + # noinspection PyUnresolvedReferences + fd = os.open(lockfile, os.O_WRONLY|os.O_NOCTTY|os.O_CREAT, 0o666) if sys.platform.startswith('aix'): # Python on AIX is compiled with LARGEFILE support, which changes the # struct size. diff --git a/tools/gyp/data/win/large-pdb-shim.cc b/tools/gyp/gyp/buildtime_helpers/large-pdb-shim.cc similarity index 100% rename from tools/gyp/data/win/large-pdb-shim.cc rename to tools/gyp/gyp/buildtime_helpers/large-pdb-shim.cc diff --git a/tools/gyp/pylib/gyp/mac_tool.py b/tools/gyp/gyp/buildtime_helpers/mac_tool.py old mode 100755 new mode 100644 similarity index 97% rename from tools/gyp/pylib/gyp/mac_tool.py rename to tools/gyp/gyp/buildtime_helpers/mac_tool.py index 0ad7e7a1b66b8a..84f88639479951 --- a/tools/gyp/pylib/gyp/mac_tool.py +++ b/tools/gyp/gyp/buildtime_helpers/mac_tool.py @@ -8,6 +8,8 @@ These functions are executed via gyp-mac-tool when using the Makefile generator. """ +from __future__ import print_function + import fcntl import fnmatch import glob @@ -16,7 +18,6 @@ import plistlib import re import shutil -import string import struct import subprocess import sys @@ -155,11 +156,11 @@ def _DetectInputEncoding(self, file_name): fp.close() return None fp.close() - if header.startswith("\xFE\xFF"): + if header.startswith(b"\xFE\xFF"): return "UTF-16" - elif header.startswith("\xFF\xFE"): + elif header.startswith(b"\xFF\xFE"): return "UTF-16" - elif header.startswith("\xEF\xBB\xBF"): + elif header.startswith(b"\xEF\xBB\xBF"): return "UTF-8" else: return None @@ -174,7 +175,7 @@ def ExecCopyInfoPlist(self, source, dest, convert_to_binary, *keys): # Insert synthesized key/value pairs (e.g. BuildMachineOSBuild). plist = plistlib.readPlistFromString(lines) if keys: - plist = dict(plist.items() + json.loads(keys[0]).items()) + plist.update(json.loads(keys[0])) lines = plistlib.writePlistToString(plist) # Go through all the environment variables and replace them as variables in @@ -185,7 +186,7 @@ def ExecCopyInfoPlist(self, source, dest, convert_to_binary, *keys): continue evar = '${%s}' % key evalue = os.environ[key] - lines = string.replace(lines, evar, evalue) + lines = lines.replace(evar, evalue) # Xcode supports various suffices on environment variables, which are # all undocumented. :rfc1034identifier is used in the standard project @@ -195,11 +196,11 @@ def ExecCopyInfoPlist(self, source, dest, convert_to_binary, *keys): # 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) + lines = lines.replace(evar, evalue) evar = '${%s:rfc1034identifier}' % key evalue = IDENT_RE.sub('-', os.environ[key]) - lines = string.replace(lines, evar, evalue) + lines = lines.replace(evar, evalue) # Remove any keys with values that haven't been replaced. lines = lines.split('\n') @@ -270,7 +271,7 @@ def ExecFilterLibtool(self, *cmd_list): _, err = libtoolout.communicate() for line in err.splitlines(): if not libtool_re.match(line) and not libtool_re5.match(line): - print >>sys.stderr, line + print(line, file=sys.stderr) # Unconditionally touch the output .a file on the command line if present # and the command succeeded. A bit hacky. if not libtoolout.returncode: @@ -385,7 +386,7 @@ def ExecCompileXcassets(self, keys, *inputs): ]) if keys: keys = json.loads(keys) - for key, value in keys.iteritems(): + for key, value in keys.items(): arg_name = '--' + key if isinstance(value, bool): if value: @@ -480,8 +481,9 @@ def _FindProvisioningProfile(self, profile, bundle_identifier): 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) + print(( + 'cannot find mobile provisioning for %s' % bundle_identifier), + file=sys.stderr) sys.exit(1) provisioning_profiles = None if profile: @@ -502,8 +504,9 @@ def _FindProvisioningProfile(self, profile, bundle_identifier): 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) + print(( + 'cannot find mobile provisioning for %s' % bundle_identifier), + file=sys.stderr) 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 @@ -527,7 +530,7 @@ def _LoadProvisioningProfile(self, profile_path): def _MergePlist(self, merged_plist, plist): """Merge |plist| into |merged_plist|.""" - for key, value in plist.iteritems(): + for key, value in plist.items(): if isinstance(value, dict): merged_value = merged_plist.get(key, {}) if isinstance(merged_value, dict): @@ -637,7 +640,7 @@ def _ExpandVariables(self, data, substitutions): the key was not found. """ if isinstance(data, str): - for key, value in substitutions.iteritems(): + for key, value in substitutions.items(): data = data.replace('$(%s)' % key, value) return data if isinstance(data, list): @@ -667,7 +670,7 @@ def WriteHmap(output_name, filelist): count = len(filelist) capacity = NextGreaterPowerOf2(count) strings_offset = 24 + (12 * capacity) - max_value_length = len(max(filelist.items(), key=lambda (k,v):len(v))[1]) + max_value_length = len(max(filelist.items(), key=lambda t: len(t[1]))[1]) out = open(output_name, "wb") out.write(struct.pack('\n%s RT_MANIFEST "%s"' % ( resource_name, os.path.abspath(manifest_path).replace('\\', '/'))) @@ -250,49 +241,42 @@ def ExecMidlWrapper(self, arch, outdir, tlb, h, dlldata, iid, proxy, idl, '/proxy', proxy, idl] env = self._GetEnv(arch) - popen = subprocess.Popen(args, shell=True, env=env, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - out, _ = popen.communicate() + out = subprocess.check_output(args, shell=True, env=env, stderr=subprocess.STDOUT).decode('utf-8') # Filter junk out of stdout, and write filtered versions. Output we want # to filter is pairs of lines that look like this: # Processing C:\Program Files (x86)\Microsoft SDKs\...\include\objidl.idl # objidl.idl lines = out.splitlines() prefixes = ('Processing ', '64 bit Processing ') - processing = set(os.path.basename(x) - for x in lines if x.startswith(prefixes)) + processing = set(os.path.basename(x) for x in lines if x.startswith(prefixes)) for line in lines: if not line.startswith(prefixes) and line not in processing: - print line - return popen.returncode + print(line) + return 0 def ExecAsmWrapper(self, arch, *args): """Filter logo banner from invocations of asm.exe.""" env = self._GetEnv(arch) - popen = subprocess.Popen(args, shell=True, env=env, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - out, _ = popen.communicate() + out = subprocess.check_output(args, shell=True, env=env, stderr=subprocess.STDOUT).decode('utf-8') for line in out.splitlines(): if (not line.startswith('Copyright (C) Microsoft Corporation') and not line.startswith('Microsoft (R) Macro Assembler') and not line.startswith(' Assembling: ') and line): - print line - return popen.returncode + print(line) + return 0 def ExecRcWrapper(self, arch, *args): """Filter logo banner from invocations of rc.exe. Older versions of RC don't support the /nologo flag.""" env = self._GetEnv(arch) - popen = subprocess.Popen(args, shell=True, env=env, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - out, _ = popen.communicate() + out = subprocess.check_output(args, shell=True, env=env, stderr=subprocess.STDOUT).decode('utf-8') for line in out.splitlines(): if (not line.startswith('Microsoft (R) Windows (R) Resource Compiler') and not line.startswith('Copyright (C) Microsoft Corporation') and line): - print line - return popen.returncode + print(line) + return 0 def ExecActionWrapper(self, arch, rspfile, *dir): """Runs an action command line from a response file using the environment @@ -300,7 +284,7 @@ def ExecActionWrapper(self, arch, rspfile, *dir): 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(): + for k, v in os.environ.items(): if k not in env: env[k] = v args = open(rspfile).read() diff --git a/tools/gyp/pylib/gyp/common.py b/tools/gyp/gyp/common.py similarity index 87% rename from tools/gyp/pylib/gyp/common.py rename to tools/gyp/gyp/common.py index a1e1db5f1239ff..0f073b0beb0917 100644 --- a/tools/gyp/pylib/gyp/common.py +++ b/tools/gyp/gyp/common.py @@ -2,19 +2,19 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -from __future__ import with_statement +from __future__ import print_function import collections import errno import filecmp +import os import os.path import re import tempfile import sys -# A minimal memoizing decorator. It'll blow up if the args aren't immutable, -# among other "problems". +# A minimal memoizing decorator. It'll blow up if the args aren't immutable, among other "problems". class memoize(object): def __init__(self, func): self.func = func @@ -92,8 +92,7 @@ def ResolveTarget(build_file, target, toolset): # interpreting it as relative to build_file. If parsed_build_file is # absolute, it is usable as a path regardless of the current directory, # and os.path.join will return it as-is. - build_file = os.path.normpath(os.path.join(os.path.dirname(build_file), - parsed_build_file)) + build_file = os.path.normpath(os.path.join(os.path.dirname(build_file), parsed_build_file)) # Further (to handle cases like ../cwd), make it relative to cwd) if not os.path.isabs(build_file): build_file = RelativePath(build_file, '.') @@ -147,31 +146,13 @@ def RelativePath(path, relative_to, follow_path_symlink=True): path = os.path.abspath(path) relative_to = os.path.realpath(relative_to) - # On Windows, we can't create a relative path to a different drive, so just - # use the absolute path. + # On Windows, we can't create a relative path to a different drive, so just use the absolute path. if sys.platform == 'win32': - if (os.path.splitdrive(path)[0].lower() != - os.path.splitdrive(relative_to)[0].lower()): + if os.path.splitdrive(path)[0].lower() != os.path.splitdrive(relative_to)[0].lower(): return path - # Split the paths into components. - path_split = path.split(os.path.sep) - relative_to_split = relative_to.split(os.path.sep) - - # Determine how much of the prefix the two paths share. - prefix_len = len(os.path.commonprefix([path_split, relative_to_split])) - - # Put enough ".." components to back up out of relative_to to the common - # prefix, and then append the part of path_split after the common prefix. - relative_split = [os.path.pardir] * (len(relative_to_split) - prefix_len) + \ - path_split[prefix_len:] - - if len(relative_split) == 0: - # The paths were the same. - return '' - - # Turn it back into a string and we're done. - return os.path.join(*relative_split) + rel = os.path.relpath(path, relative_to) + return rel @memoize @@ -280,15 +261,16 @@ def EncodePOSIXShellArgument(argument): return encoded -def EncodePOSIXShellList(list): - """Encodes |list| suitably for consumption by POSIX shells. +def EncodePOSIXShellList(lst): + """ + Encodes |lst| suitably for consumption by POSIX shells. - Returns EncodePOSIXShellArgument for each item in list, and joins them + Returns EncodePOSIXShellArgument for each item in lst, and joins them together using the space character as an argument separator. """ encoded_arguments = [] - for argument in list: + for argument in lst: encoded_arguments.append(EncodePOSIXShellArgument(argument)) return ' '.join(encoded_arguments) @@ -341,11 +323,12 @@ class Writer(object): def __init__(self): # Pick temporary file. tmp_fd, self.tmp_path = tempfile.mkstemp( - suffix='.tmp', - prefix=os.path.split(filename)[1] + '.gyp.', - dir=os.path.split(filename)[0]) + suffix='.tmp', + prefix=os.path.split(filename)[1] + '.gyp.', + dir=os.path.split(filename)[0] + ) try: - self.tmp_file = os.fdopen(tmp_fd, 'wb') + self.tmp_file = os.fdopen(tmp_fd, 'w') except Exception: # Don't leave turds behind. os.unlink(self.tmp_path) @@ -363,13 +346,12 @@ def close(self): same = False try: same = filecmp.cmp(self.tmp_path, filename, False) - except OSError, e: + except OSError as e: if e.errno != errno.ENOENT: raise if same: - # The new file is identical to the old one, just get rid of the new - # one. + # The new file is identical to the old one, just get rid of the new one. os.unlink(self.tmp_path) else: # The new file is different from the old one, or there is no old one. @@ -382,9 +364,9 @@ def close(self): # # No way to get the umask without setting a new one? Set a safe one # and then set it back to the old value. - umask = os.umask(077) + umask = os.umask(0o77) os.umask(umask) - os.chmod(self.tmp_path, 0666 & ~umask) + os.chmod(self.tmp_path, 0o666 & ~umask) if sys.platform == 'win32' and os.path.exists(filename): # NOTE: on windows (but not cygwin) rename will not replace an # existing file, so it must be preceded with a remove. Sadly there @@ -414,7 +396,6 @@ def GetFlavor(params): 'win32': 'win', 'darwin': 'mac', } - if 'flavor' in params: return params['flavor'] if sys.platform in flavors: @@ -429,45 +410,54 @@ def GetFlavor(params): return 'netbsd' if sys.platform.startswith('aix'): return 'aix' - + if sys.platform.startswith('zos'): + return 'zos' + if sys.platform.startswith('os390'): + return 'zos' return 'linux' -def CopyTool(flavor, out_path, generator_flags={}): - """Finds (flock|mac|win)_tool.gyp in the gyp directory and copies it - to |out_path|.""" - # aix and solaris just need flock emulation. mac and win use more complicated - # support scripts. +def CopyTool(flavor, out_path, mac_toolchain_dir=None): + """ + Finds (flock|mac|win)_tool.py in the gyp directory and copies it to |out_path|. + Refs: flock_tool.py => gyp-flock-tool + Refs: mac_tool.py => gyp-mac-tool + Refs: win_tool.py => gyp-win-tool + """ + # 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) + 'aix': 'flock', + 'solaris': 'flock', + 'mac': 'mac', + 'win': 'win' + }.get(flavor) if not prefix: return # Slurp input file. - source_path = os.path.join( - os.path.dirname(os.path.abspath(__file__)), '%s_tool.py' % prefix) - with open(source_path) as source_file: + source_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'buildtime_helpers', '%s_tool.py' % prefix) + with open(source_path, 'rt') as source_file: source = source_file.readlines() # Set custom header flags. - header = '# Generated by gyp. Do not edit.\n' - mac_toolchain_dir = generator_flags.get('mac_toolchain_dir', None) + headers = [ + source.pop(0), # original shebang + '# Generated by gyp. Do not edit.\n' + ] if flavor == 'mac' and mac_toolchain_dir: - header += "import os;\nos.environ['DEVELOPER_DIR']='%s'\n" \ - % mac_toolchain_dir + headers += [ + 'import os\n', + "os.environ['DEVELOPER_DIR']='%s'\n" % mac_toolchain_dir + ] # Add header and write it out. tool_path = os.path.join(out_path, 'gyp-%s-tool' % prefix) - with open(tool_path, 'w') as tool_file: - tool_file.write( - ''.join([source[0], header] + source[1:])) + with open(tool_path, 'wt') as tool_file: + tool_src_lines = headers + source + tool_file.writelines(tool_src_lines) # Make file executable. - os.chmod(tool_path, 0755) + os.chmod(tool_path, 0o755) # From Alex Martelli, @@ -475,7 +465,6 @@ def CopyTool(flavor, out_path, generator_flags={}): # ASPN: Python Cookbook: Remove duplicates from a sequence # First comment, dated 2001/10/13. # (Also in the printed Python Cookbook.) - def uniquer(seq, idfun=None): if idfun is None: idfun = lambda x: x @@ -496,7 +485,7 @@ def __init__(self, iterable=None): end += [None, end, end] # sentinel node for doubly linked list self.map = {} # key --> [key, prev, next] if iterable is not None: - self |= iterable + self.update(iterable) def __len__(self): return len(self.map) @@ -564,7 +553,8 @@ def __str__(self): def TopologicallySorted(graph, get_edges): - r"""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. @@ -580,7 +570,7 @@ def TopologicallySorted(graph, get_edges): graph = {'a': '$(b) $(c)', 'b': 'hi', 'c': '$(b)'} def GetEdges(node): return re.findall(r'\$\(([^))]\)', graph[node]) - print TopologicallySorted(graph.keys(), GetEdges) + print(TopologicallySorted(graph.keys(), GetEdges)) ==> ['a', 'c', b'] """ @@ -588,21 +578,22 @@ def GetEdges(node): visited = set() visiting = set() ordered_nodes = [] - def Visit(node): - if node in visiting: + def Visit(n): + if n in visiting: raise CycleError(visiting) - if node in visited: + if n in visited: return - visited.add(node) - visiting.add(node) - for neighbor in get_edges(node): + visited.add(n) + visiting.add(n) + for neighbor in get_edges(n): Visit(neighbor) - visiting.remove(node) - ordered_nodes.insert(0, node) + visiting.remove(n) + ordered_nodes.insert(0, n) 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. @@ -613,3 +604,18 @@ def CrossCompileRequested(): os.environ.get('AR_target') or os.environ.get('CC_target') or os.environ.get('CXX_target')) + + +def IsStrCanonicalInt(string): + """ + Returns True if |string| is a canonical integer form str. + The canonical form is such that str(int(string)) == string. + """ + if type(string) is not str: + return False + # noinspection PyBroadException + try: + i = int(string) + return str(i) == string + except: + return False diff --git a/tools/gyp/pylib/gyp/easy_xml.py b/tools/gyp/gyp/easy_xml.py similarity index 89% rename from tools/gyp/pylib/gyp/easy_xml.py rename to tools/gyp/gyp/easy_xml.py index 2522efb244d0a3..e0d0ab0ac6fcc6 100644 --- a/tools/gyp/pylib/gyp/easy_xml.py +++ b/tools/gyp/gyp/easy_xml.py @@ -3,9 +3,11 @@ # found in the LICENSE file. import re -import os import locale +if 'reduce' not in __builtins__: + from functools import reduce + def XmlToString(content, encoding='utf-8', pretty=False): """ Writes the XML content to disk, touching the file only if it has changed. @@ -80,7 +82,7 @@ def _ConstructContentList(xml_parts, specification, pretty, level=0): # Optionally in second position is a dictionary of the attributes. rest = specification[1:] if rest and isinstance(rest[0], dict): - for at, val in sorted(rest[0].iteritems()): + for at, val in sorted(rest[0].items()): xml_parts.append(' %s="%s"' % (at, _XmlEscape(val, attr=True))) rest = rest[1:] if rest: @@ -103,8 +105,7 @@ def _ConstructContentList(xml_parts, specification, pretty, level=0): xml_parts.append('/>%s' % new_line) -def WriteXmlIfChanged(content, path, encoding='utf-8', pretty=False, - win32=False): +def WriteXmlIfChanged(content, path, encoding='utf-8', pretty=False, win32=False): """ Writes the XML content to disk, touching the file only if it has changed. Args: @@ -112,28 +113,27 @@ def WriteXmlIfChanged(content, path, encoding='utf-8', pretty=False, path: Location of the file. encoding: The encoding to report on the first line of the XML file. pretty: True if we want pretty printing with indents and new lines. + win32: True if we want \r\n as line terminator. """ xml_string = XmlToString(content, encoding, pretty) - if win32 and os.linesep != '\r\n': - xml_string = xml_string.replace('\n', '\r\n') - default_encoding = locale.getdefaultlocale()[1] if default_encoding and default_encoding.upper() != encoding.upper(): - xml_string = xml_string.decode(default_encoding).encode(encoding) + if hasattr(xml_string, 'decode'): + xml_string = xml_string.decode(default_encoding) # Get the old content try: - f = open(path, 'r') - existing = f.read() - f.close() + with open(path, 'r') as f: + existing = f.read().decode(encoding, 'ignore') except: existing = None # It has changed, write it - if existing != xml_string: - f = open(path, 'w') - f.write(xml_string) - f.close() + if existing == xml_string: + return + + with open(path, 'wb') as f: + f.write(xml_string.encode('utf-8')) _xml_escape_map = { @@ -147,8 +147,7 @@ def WriteXmlIfChanged(content, path, encoding='utf-8', pretty=False, } -_xml_escape_re = re.compile( - "(%s)" % "|".join(map(re.escape, _xml_escape_map.keys()))) +_xml_escape_re = re.compile("(%s)" % "|".join(map(re.escape, _xml_escape_map.keys()))) def _XmlEscape(value, attr=False): diff --git a/tools/gyp/pylib/gyp/generator/__init__.py b/tools/gyp/gyp/generator/__init__.py similarity index 100% rename from tools/gyp/pylib/gyp/generator/__init__.py rename to tools/gyp/gyp/generator/__init__.py diff --git a/tools/gyp/pylib/gyp/generator/analyzer.py b/tools/gyp/gyp/generator/analyzer.py similarity index 92% rename from tools/gyp/pylib/gyp/generator/analyzer.py rename to tools/gyp/gyp/generator/analyzer.py index 921c1a6b714328..5d2e5388b2a0d4 100644 --- a/tools/gyp/pylib/gyp/generator/analyzer.py +++ b/tools/gyp/gyp/generator/analyzer.py @@ -62,12 +62,13 @@ then the "all" target includes "b1" and "b2". """ -import gyp.common -import gyp.ninja_syntax as ninja_syntax +from __future__ import print_function + import json import os import posixpath -import sys +import gyp.msvs_emulation +import gyp.common debug = False @@ -155,7 +156,7 @@ def _AddSources(sources, base_path, base_path_components, result): continue result.append(base_path + source) if debug: - print 'AddSource', org_source, result[len(result) - 1] + print('AddSource', org_source, result[len(result) - 1]) def _ExtractSourcesFromAction(action, base_path, base_path_components, @@ -185,7 +186,7 @@ def _ExtractSources(target, target_dict, toplevel_dir): base_path += '/' if debug: - print 'ExtractSources', target, base_path + print('ExtractSources', target, base_path) results = [] if 'sources' in target_dict: @@ -278,7 +279,7 @@ def _WasBuildFileModified(build_file, data, files, toplevel_dir): the root of the source tree.""" if _ToLocalPath(toplevel_dir, _ToGypPath(build_file)) in files: if debug: - print 'gyp file modified', build_file + print('gyp file modified', build_file) return True # First element of included_files is the file itself. @@ -291,8 +292,7 @@ def _WasBuildFileModified(build_file, data, files, toplevel_dir): _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 + print('included gyp file modified, gyp_file=', build_file, 'included file=', rel_include_file) return True return False @@ -373,7 +373,7 @@ def _GenerateTargets(data, target_list, target_dicts, toplevel_dir, files, # 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 + print('matching target from modified build file', target_name) target.match_status = MATCH_STATUS_MATCHES matching_targets.append(target) else: @@ -381,7 +381,7 @@ def _GenerateTargets(data, target_list, target_dicts, toplevel_dir, files, toplevel_dir) for source in sources: if _ToGypPath(os.path.normpath(source)) in files: - print 'target', target_name, 'matches', source + print('target', target_name, 'matches', source) target.match_status = MATCH_STATUS_MATCHES matching_targets.append(target) break @@ -433,7 +433,7 @@ def _DoesTargetDependOnMatchingTargets(target): for dep in target.deps: if _DoesTargetDependOnMatchingTargets(dep): target.match_status = MATCH_STATUS_MATCHES_BY_DEPENDENCY - print '\t', target.name, 'matches by dep', dep.name + print('\t', target.name, 'matches by dep', dep.name) return True target.match_status = MATCH_STATUS_DOESNT_MATCH return False @@ -445,7 +445,7 @@ def _GetTargetsDependingOnMatchingTargets(possible_targets): supplied as input to analyzer. possible_targets: targets to search from.""" found = [] - print 'Targets that matched by dependency:' + print('Targets that matched by dependency:') for target in possible_targets: if _DoesTargetDependOnMatchingTargets(target): found.append(target) @@ -484,12 +484,13 @@ def _AddCompileTargets(target, roots, add_if_no_ancestor, result): (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 compile 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, \ + print('\t\tadding to compile 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 @@ -500,7 +501,7 @@ def _GetCompileTargets(matching_targets, supplied_targets): supplied_targets: set of targets supplied to analyzer to search from.""" result = set() for target in matching_targets: - print 'finding compile targets for match', target.name + print('finding compile targets for match', target.name) _AddCompileTargets(target, supplied_targets, True, result) return result @@ -508,46 +509,46 @@ def _GetCompileTargets(matching_targets, supplied_targets): def _WriteOutput(params, **values): """Writes the output, either to stdout or a file is specified.""" if 'error' in values: - print 'Error:', values['error'] + print('Error:', values['error']) if 'status' in values: - print values['status'] + print(values['status']) if 'targets' in values: values['targets'].sort() - print 'Supplied targets that depend on changed files:' + print('Supplied targets that depend on changed files:') for target in values['targets']: - print '\t', target + print('\t', target) if 'invalid_targets' in values: values['invalid_targets'].sort() - print 'The following targets were not found:' + print('The following targets were not found:') for target in values['invalid_targets']: - print '\t', target + print('\t', target) if 'build_targets' in values: values['build_targets'].sort() - print 'Targets that require a build:' + print('Targets that require a build:') for target in values['build_targets']: - print '\t', target + print('\t', target) if 'compile_targets' in values: values['compile_targets'].sort() - print 'Targets that need to be built:' + print('Targets that need to be built:') for target in values['compile_targets']: - print '\t', target + print('\t', target) if 'test_targets' in values: values['test_targets'].sort() - print 'Test targets:' + print('Test targets:') for target in values['test_targets']: - print '\t', target + print('\t', target) output_path = params.get('generator_flags', {}).get( 'analyzer_output_path', None) if not output_path: - print json.dumps(values) + 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) + print('Error writing to output file', output_path, str(e)) def _WasGypIncludeFileModified(params, files): @@ -556,7 +557,7 @@ def _WasGypIncludeFileModified(params, 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 + print('Include file modified, assuming all changed', include) return True return False @@ -579,14 +580,10 @@ def CalculateVariables(default_variables, params): 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', []) - + # # 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 @@ -638,13 +635,13 @@ def find_matching_test_target_names(self): set(self._root_targets))] else: test_targets = [x for x in test_targets_no_all] - print 'supplied test_targets' + print('supplied test_targets') for target_name in self._test_target_names: - print '\t', target_name - print 'found test_targets' + print('\t', target_name) + print('found test_targets') for target in test_targets: - print '\t', target.name - print 'searching for matching test targets' + print('\t', target.name) + print('searching for matching test targets') matching_test_targets = _GetTargetsDependingOnMatchingTargets(test_targets) matching_test_targets_contains_all = (test_target_names_contains_all and set(matching_test_targets) & @@ -654,14 +651,14 @@ def find_matching_test_target_names(self): # 'all' is subsequentely added to the matching names below. matching_test_targets = [x for x in (set(matching_test_targets) & set(test_targets_no_all))] - print 'matched test_targets' + print('matched test_targets') for target in matching_test_targets: - print '\t', target.name + print('\t', target.name) matching_target_names = [gyp.common.ParseQualifiedTarget(target.name)[1] for target in matching_test_targets] if matching_test_targets_contains_all: matching_target_names.append('all') - print '\tall' + print('\tall') return matching_target_names def find_matching_compile_target_names(self): @@ -669,7 +666,7 @@ def find_matching_compile_target_names(self): assert self.is_build_impacted(); # Compile targets are found by searching up from changed targets. # Reset the visited status for _GetBuildTargets. - for target in self._name_to_target.itervalues(): + for target in self._name_to_target.values(): target.visited = False supplied_targets = _LookupTargets(self._supplied_target_names_no_all(), @@ -677,10 +674,10 @@ def find_matching_compile_target_names(self): if 'all' in self._supplied_target_names(): supplied_targets = [x for x in (set(supplied_targets) | set(self._root_targets))] - print 'Supplied test_targets & compile_targets' + print('Supplied test_targets & compile_targets') for target in supplied_targets: - print '\t', target.name - print 'Finding compile targets' + print('\t', target.name) + print('Finding compile targets') compile_targets = _GetCompileTargets(self._changed_targets, supplied_targets) return [gyp.common.ParseQualifiedTarget(target.name)[1] @@ -699,7 +696,7 @@ def GenerateOutput(target_list, target_dicts, data, params): toplevel_dir = _ToGypPath(os.path.abspath(params['options'].toplevel_dir)) if debug: - print 'toplevel_dir', toplevel_dir + print('toplevel_dir', toplevel_dir) if _WasGypIncludeFileModified(params, config.files): result_dict = { 'status': all_changed_string, diff --git a/tools/gyp/pylib/gyp/generator/cmake.py b/tools/gyp/gyp/generator/cmake.py similarity index 86% rename from tools/gyp/pylib/gyp/generator/cmake.py rename to tools/gyp/gyp/generator/cmake.py index a2b96291aa526a..e5cb24cbe739ca 100644 --- a/tools/gyp/pylib/gyp/generator/cmake.py +++ b/tools/gyp/gyp/generator/cmake.py @@ -28,14 +28,20 @@ CMakeLists.txt file. """ -import multiprocessing +from __future__ import print_function + import os -import signal import string import subprocess import gyp.common import gyp.xcode_emulation +try: + _maketrans = str.maketrans +except NameError: + # noinspection PyUnresolvedReferences + _maketrans = string.maketrans + generator_default_variables = { 'EXECUTABLE_PREFIX': '', 'EXECUTABLE_SUFFIX': '', @@ -104,8 +110,7 @@ def NormjoinPathForceCMakeSource(base_path, 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_CURRENT_LIST_DIR}', - os.path.normpath(os.path.join(base_path, rel_path))) + return os.path.join('${CMAKE_CURRENT_LIST_DIR}', os.path.normpath(os.path.join(base_path, rel_path))) def NormjoinPath(base_path, rel_path): @@ -238,11 +243,10 @@ def StringToCMakeTargetName(a): Invalid for make: ':' Invalid for unknown reasons but cause failures: '.' """ - return a.translate(string.maketrans(' /():."', '_______')) + return a.translate(_maketrans(' /():."', '_______')) -def WriteActions(target_name, actions, extra_sources, extra_deps, - path_to_gyp, output): +def WriteActions(target_name, actions, extra_sources, extra_deps, path_to_gyp, output): """Write CMake for the 'actions' in the target. Args: @@ -259,12 +263,10 @@ def WriteActions(target_name, actions, extra_sources, extra_deps, inputs = action['inputs'] inputs_name = action_target_name + '__input' - SetVariableList(output, inputs_name, - [NormjoinPathForceCMakeSource(path_to_gyp, dep) for dep in inputs]) + 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] + cmake_outputs = [NormjoinPathForceCMakeSource(path_to_gyp, out) for out in outputs] outputs_name = action_target_name + '__output' SetVariableList(output, outputs_name, cmake_outputs) @@ -321,19 +323,18 @@ def WriteActions(target_name, actions, extra_sources, extra_deps, def NormjoinRulePathForceCMakeSource(base_path, rel_path, rule_source): - if rel_path.startswith(("${RULE_INPUT_PATH}","${RULE_INPUT_DIRNAME}")): + 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): +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. + rules: the Gyp 'rules' 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 @@ -344,8 +345,7 @@ def WriteRules(target_name, rules, extra_sources, extra_deps, inputs = rule.get('inputs', []) inputs_name = rule_name + '__input' - SetVariableList(output, inputs_name, - [NormjoinPathForceCMakeSource(path_to_gyp, dep) for dep in inputs]) + SetVariableList(output, inputs_name, [NormjoinPathForceCMakeSource(path_to_gyp, dep) for dep in inputs]) outputs = rule['outputs'] var_outputs = [] @@ -369,9 +369,7 @@ def WriteRules(target_name, rules, extra_sources, extra_deps, 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)) + 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 + '}') @@ -446,7 +444,7 @@ def WriteCopies(target_name, copies, extra_deps, path_to_gyp, output): Args: target_name: the name of the CMake target being generated. - actions: the Gyp 'actions' dict for this target. + copies: the Gyp 'copies' 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. @@ -551,8 +549,7 @@ def __init__(self, ext, command): 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)) + _, 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 @@ -561,8 +558,7 @@ def CreateCMakeTargetBaseName(qualified_target): def CreateCMakeTargetFullName(qualified_target): """An unambiguous name for the target.""" - gyp_file, gyp_target_name, gyp_target_toolset = ( - gyp.common.ParseQualifiedTarget(qualified_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 @@ -589,6 +585,7 @@ class CMakeNamer(object): 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() @@ -608,9 +605,7 @@ def CreateCMakeTargetName(self, qualified_target): return base_name -def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, - options, generator_flags, all_qualified_targets, flavor, - output): +def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, options, generator_flags, all_qualified_targets, flavor, 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) @@ -644,8 +639,7 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, 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 ) ) + print('Target %s has unknown target type %s, skipping.' % (target_name, target_type)) return SetVariable(output, 'TARGET', target_name) @@ -658,18 +652,15 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, # 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) + 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) + 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) + WriteCopies(cmake_target_name, spec['copies'], extra_deps, path_from_cmakelists_to_gyp, output) # Target and sources srcs = spec.get('sources', []) @@ -748,8 +739,7 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, 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") + SetVariable(output, dummy_sources_name, "${obj}.${TOOLSET}/${TARGET}/genc/dummy.c") output.write('if(NOT EXISTS "') WriteVariable(output, dummy_sources_name) output.write('")\n') @@ -758,7 +748,6 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, 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. @@ -799,13 +788,10 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, 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) + 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) + SetTargetProperty(output, extra_target_name, 'EXCLUDE_FROM_ALL', exclude_from_all) # Output name and location. if target_type != 'none': @@ -835,19 +821,12 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, 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) + 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)) + 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) + 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 = '' @@ -855,21 +834,18 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, 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_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_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) + 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) @@ -880,15 +856,12 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, 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, 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) + cmake_target_output = os.path.join(cmake_target_output_directory, cmake_target_output_basename) SetFileProperty(output, cmake_target_output, 'GENERATED', ['TRUE'], '') # Includes @@ -896,9 +869,7 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, 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]) + 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 ') @@ -908,11 +879,7 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, # Defines defines = config.get('defines') if defines is not None: - SetTargetProperty(output, - cmake_target_name, - 'COMPILE_DEFINITIONS', - defines, - ';') + 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. @@ -935,9 +902,7 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, if xcode_settings: cflags = xcode_settings.GetCflags(config_to_use) cflags_c = xcode_settings.GetCflagsC(config_to_use) - cflags_cxx = xcode_settings.GetCflagsCC(config_to_use) - #cflags_objc = xcode_settings.GetCflagsObjC(config_to_use) - #cflags_objcc = xcode_settings.GetCflagsObjCC(config_to_use) + cflags_cxx = xcode_settings.GetCflagsCC(config_to_use) # cflags_objc = xcode_settings.GetCflagsObjC(config_to_use) # cflags_objcc = xcode_settings.GetCflagsObjCC(config_to_use) if (not cflags_c or not c_sources) and (not cflags_cxx or not cxx_sources): SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', cflags, ' ') @@ -980,9 +945,7 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, # XCode settings xcode_settings = config.get('xcode_settings', {}) for xcode_setting, xcode_value in xcode_settings.viewitems(): - SetTargetProperty(output, cmake_target_name, - "XCODE_ATTRIBUTE_%s" % xcode_setting, xcode_value, - '' if isinstance(xcode_value, str) else ' ') + SetTargetProperty(output, cmake_target_name, "XCODE_ATTRIBUTE_%s" % xcode_setting, xcode_value, '' if isinstance(xcode_value, str) else ' ') # Note on Dependencies and Libraries: # CMake wants to handle link order, resolving the link line up front. @@ -1003,7 +966,7 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, if dep_target_type == 'static_library': static_deps.append(dep_cmake_name) - elif dep_target_type == 'shared_library': + elif dep_target_type == 'shared_library': shared_deps.append(dep_cmake_name) else: other_deps.append(dep_cmake_name) @@ -1074,8 +1037,7 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, UnsetVariable(output, 'TARGET') -def GenerateOutputForConfig(target_list, target_dicts, data, - params, config_to_use): +def GenerateOutputForConfig(target_list, target_dicts, data, params, config_to_use): options = params['options'] generator_flags = params['generator_flags'] flavor = gyp.common.GetFlavor(params) @@ -1091,9 +1053,7 @@ def GenerateOutputForConfig(target_list, target_dicts, data, # 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)) + 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) @@ -1116,8 +1076,7 @@ def GenerateOutputForConfig(target_list, target_dicts, data, cxx = None make_global_settings = data[gyp_file].get('make_global_settings', []) - build_to_top = gyp.common.InvertRelativePath(build_dir, - options.toplevel_dir) + 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) @@ -1172,9 +1131,7 @@ def GenerateOutputForConfig(target_list, target_dicts, data, # 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)): + 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: @@ -1183,13 +1140,12 @@ def GenerateOutputForConfig(target_list, target_dicts, data, spec = target_dicts[qualified_target] gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[gyp_file], spec) - WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, - options, generator_flags, all_qualified_targets, flavor, output) + WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, options, generator_flags, all_qualified_targets, flavor, output) output.close() -def PerformBuild(data, configurations, params): +def PerformBuild(_, configurations, params): options = params['options'] generator_flags = params['generator_flags'] @@ -1203,46 +1159,21 @@ def PerformBuild(data, configurations, params): 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)) + 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) + 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) + 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) + 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) + config_names = target_dicts[target_list[0]]['configurations'] + for config_name in config_names: + GenerateOutputForConfig(target_list, target_dicts, data, params, config_name) diff --git a/tools/gyp/pylib/gyp/generator/dump_dependency_json.py b/tools/gyp/gyp/generator/dump_dependency_json.py similarity index 84% rename from tools/gyp/pylib/gyp/generator/dump_dependency_json.py rename to tools/gyp/gyp/generator/dump_dependency_json.py index 160eafe2efeca0..d0bb303413bca7 100644 --- a/tools/gyp/pylib/gyp/generator/dump_dependency_json.py +++ b/tools/gyp/gyp/generator/dump_dependency_json.py @@ -2,13 +2,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import collections +from __future__ import print_function + import os import gyp import gyp.common import gyp.msvs_emulation import json -import sys generator_supports_multiple_toolsets = True @@ -40,14 +40,10 @@ def CalculateVariables(default_variables, params): flavor = gyp.common.GetFlavor(params) if flavor =='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', []) - + # # 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) @@ -71,7 +67,7 @@ def CalculateGeneratorInputInfo(params): 'qualified_out_dir': qualified_out_dir, } -def GenerateOutput(target_list, target_dicts, data, params): +def GenerateOutput(target_list, target_dicts, _, params): # Map of target -> list of targets it depends on. edges = {} @@ -96,4 +92,4 @@ def GenerateOutput(target_list, target_dicts, data, params): f = open(filename, 'w') json.dump(edges, f) f.close() - print 'Wrote json to %s.' % filename + print('Wrote json to %s.' % filename) diff --git a/tools/gyp/pylib/gyp/generator/eclipse.py b/tools/gyp/gyp/generator/eclipse.py similarity index 86% rename from tools/gyp/pylib/gyp/generator/eclipse.py rename to tools/gyp/gyp/generator/eclipse.py index 3544347b3bacd4..3d63f3849101c8 100644 --- a/tools/gyp/pylib/gyp/generator/eclipse.py +++ b/tools/gyp/gyp/generator/eclipse.py @@ -57,14 +57,10 @@ def CalculateVariables(default_variables, 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', []) - + # # 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) @@ -118,8 +114,6 @@ def GetAllIncludeDirectories(target_list, target_dicts, 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']: @@ -130,6 +124,7 @@ def GetAllIncludeDirectories(target_list, target_dicts, # TODO(jgreenwald): Change the gyp files to not abuse cflags for this, and # remove this. if flavor == 'win': + generator_flags = params.get('generator_flags', {}) msvs_settings = gyp.msvs_emulation.MsvsSettings(target, generator_flags) cflags = msvs_settings.GetCflags(config_name) else: @@ -141,7 +136,7 @@ def GetAllIncludeDirectories(target_list, target_dicts, compiler_includes_list.append(include_dir) # Find standard gyp include dirs. - if config.has_key('include_dirs'): + if 'include_dirs' in config: include_dirs = config['include_dirs'] for shared_intermediate_dir in shared_intermediate_dirs: for include_dir in include_dirs: @@ -190,8 +185,7 @@ def GetCompilerPath(target_list, data, options): return 'gcc' -def GetAllDefines(target_list, target_dicts, data, config_name, params, - compiler_path): +def GetAllDefines(target_list, target_dicts, _, config_name, params, compiler_path): """Calculate the defines for a project. Returns: @@ -202,12 +196,11 @@ def GetAllDefines(target_list, target_dicts, data, config_name, params, # 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': + generator_flags = params.get('generator_flags', {}) msvs_settings = gyp.msvs_emulation.MsvsSettings(target, generator_flags) extra_defines = msvs_settings.GetComputedDefines(config_name) else: @@ -252,14 +245,12 @@ def GetAllDefines(target_list, target_dicts, data, config_name, params, def WriteIncludePaths(out, eclipse_langs, include_dirs): """Write the includes section of a CDT settings export file.""" - out.write('
\n') + out.write('
\n') out.write(' \n') for lang in eclipse_langs: out.write(' \n' % lang) for include_dir in include_dirs: - out.write(' %s\n' % - include_dir) + out.write(' %s\n' % include_dir) out.write(' \n') out.write('
\n') @@ -267,78 +258,68 @@ def WriteIncludePaths(out, eclipse_langs, include_dirs): def WriteMacros(out, eclipse_langs, defines): """Write the macros section of a CDT settings export file.""" - out.write('
\n') + out.write('
\n') out.write(' \n') for lang in eclipse_langs: out.write(' \n' % lang) - for key in sorted(defines.iterkeys()): - out.write(' %s%s\n' % - (escape(key), escape(defines[key]))) + for key in sorted(defines.keys()): + out.write(' %s%s\n' % (escape(key), escape(defines[key]))) out.write(' \n') out.write('
\n') -def GenerateOutputForConfig(target_list, target_dicts, data, params, - config_name): +def GenerateOutputForConfig(target_list, target_dicts, data, params, config_name): options = params['options'] generator_flags = params.get('generator_flags', {}) # build_dir: relative path from source root to our output files. # e.g. "out/Debug" - build_dir = os.path.join(generator_flags.get('output_dir', 'out'), - config_name) + build_dir = os.path.join(generator_flags.get('output_dir', 'out'), config_name) toplevel_build = os.path.join(options.toplevel_dir, build_dir) # Ninja uses out/Debug/gen while make uses out/Debug/obj/gen as the # SHARED_INTERMEDIATE_DIR. Include both possible locations. - shared_intermediate_dirs = [os.path.join(toplevel_build, 'obj', 'gen'), - os.path.join(toplevel_build, 'gen')] + shared_intermediate_dirs = [ + os.path.join(toplevel_build, 'obj', 'gen'), + os.path.join(toplevel_build, 'gen') + ] GenerateCdtSettingsFile(target_list, target_dicts, data, params, config_name, - os.path.join(toplevel_build, - 'eclipse-cdt-settings.xml'), + 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')) + os.path.join(toplevel_build, 'eclipse-classpath.xml')) -def GenerateCdtSettingsFile(target_list, target_dicts, data, params, - config_name, out_name, options, - shared_intermediate_dirs): +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'] + 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) + 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) + 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.''' +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') @@ -357,7 +338,7 @@ def AddElements(kind, paths): entry_element.set('kind', kind) entry_element.set('path', path) - AddElements('lib', GetJavaJars(target_list, target_dicts, toplevel_dir)) + AddElements('lib', GetJavaJars(target_list, target_dicts)) 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']) @@ -368,8 +349,8 @@ def AddElements(kind, paths): ET.ElementTree(result).write(out_name) -def GetJavaJars(target_list, target_dicts, toplevel_dir): - '''Generates a sequence of all .jars used as inputs.''' +def GetJavaJars(target_list, target_dicts): + """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', []): @@ -382,7 +363,7 @@ def GetJavaJars(target_list, target_dicts, toplevel_dir): def GetJavaSourceDirs(target_list, target_dicts, toplevel_dir): - '''Generates a sequence of all likely java package root directories.''' + """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', []): @@ -418,7 +399,7 @@ def GenerateOutput(target_list, target_dicts, data, params): GenerateOutputForConfig(target_list, target_dicts, data, params, user_config) else: - config_names = target_dicts[target_list[0]]['configurations'].keys() + config_names = target_dicts[target_list[0]]['configurations'] for config_name in config_names: GenerateOutputForConfig(target_list, target_dicts, data, params, config_name) diff --git a/tools/gyp/pylib/gyp/generator/gypd.py b/tools/gyp/gyp/generator/gypd.py similarity index 93% rename from tools/gyp/pylib/gyp/generator/gypd.py rename to tools/gyp/gyp/generator/gypd.py index 3efdb9966a69a1..568f6d1193620e 100644 --- a/tools/gyp/pylib/gyp/generator/gypd.py +++ b/tools/gyp/gyp/generator/gypd.py @@ -32,8 +32,6 @@ import gyp.common -import errno -import os import pprint @@ -74,11 +72,10 @@ generator_default_variables[v] = '<(%s)' % v -def GenerateOutput(target_list, target_dicts, data, params): +def GenerateOutput(target_list, _, data, params): output_files = {} for qualified_target in target_list: - [input_file, target] = \ - gyp.common.ParseQualifiedTarget(qualified_target)[0:2] + [input_file, __] = gyp.common.ParseQualifiedTarget(qualified_target)[0:2] if input_file[-4:] != '.gyp': continue @@ -88,7 +85,7 @@ def GenerateOutput(target_list, target_dicts, data, params): if not output_file in output_files: output_files[output_file] = input_file - for output_file, input_file in output_files.iteritems(): + for output_file, input_file in output_files.items(): output = open(output_file, 'w') pprint.pprint(data[input_file], output) output.close() diff --git a/tools/gyp/pylib/gyp/generator/gypsh.py b/tools/gyp/gyp/generator/gypsh.py similarity index 84% rename from tools/gyp/pylib/gyp/generator/gypsh.py rename to tools/gyp/gyp/generator/gypsh.py index bd405f43a993d4..dcd9e24f97b5da 100644 --- a/tools/gyp/pylib/gyp/generator/gypsh.py +++ b/tools/gyp/gyp/generator/gypsh.py @@ -40,8 +40,8 @@ generator_default_variables[v] = '<(%s)' % v -def GenerateOutput(target_list, target_dicts, data, params): - locals = { +def GenerateOutput(target_list, target_dicts, data, _): + locals_vars = { 'target_list': target_list, 'target_dicts': target_dicts, 'data': data, @@ -50,7 +50,7 @@ def GenerateOutput(target_list, target_dicts, data, params): # Use a banner that looks like the stock Python one and like what # code.interact uses by default, but tack on something to indicate what # locals are available, and identify gypsh. - banner='Python %s on %s\nlocals.keys() = %s\ngypsh' % \ - (sys.version, sys.platform, repr(sorted(locals.keys()))) + locals_repr = repr(sorted(locals_vars.keys())) + banner='Python %s on %s\nlocals.keys() = %s\ngypsh' % (sys.version, sys.platform, locals_repr) - code.interact(banner, local=locals) + code.interact(banner, local=locals_vars) diff --git a/tools/gyp/gyp/generator/make.py b/tools/gyp/gyp/generator/make.py new file mode 100644 index 00000000000000..4b5b7e92dd1f3e --- /dev/null +++ b/tools/gyp/gyp/generator/make.py @@ -0,0 +1,557 @@ +# 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. + +# Notes: +# +# This is all roughly based on the Makefile system used by the Linux +# kernel, but is a non-recursive make -- we put the entire dependency +# graph in front of make and let it figure it out. +# +# The code below generates a separate .mk file for each target, but +# all are sourced by the top-level Makefile. This means that all +# variables in .mk-files clobber one another. Be careful to use := +# where appropriate for immediate evaluation, and similarly to watch +# that you're not relying on a variable value to last beween different +# .mk files. +# + +# TODO +# Global settings and utility functions are currently stuffed in the toplevel Makefile. +# It may make sense to generate some .mk files on the side to keep the the files readable. + +from __future__ import print_function + +import os +import re +import subprocess +import gyp +import gyp.common +import gyp.xcode_emulation +from gyp.common import GetEnvironFallback + +generator_default_variables = { + 'EXECUTABLE_PREFIX': '', + 'EXECUTABLE_SUFFIX': '', + 'STATIC_LIB_PREFIX': 'lib', + 'SHARED_LIB_PREFIX': 'lib', + 'STATIC_LIB_SUFFIX': '.a', + 'INTERMEDIATE_DIR': '$(obj).$(TOOLSET)/$(TARGET)/geni', + 'SHARED_INTERMEDIATE_DIR': '$(obj)/gen', + 'PRODUCT_DIR': '$(builddir)', + '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': '$(abspath $<)', + 'RULE_INPUT_EXT': '$(suffix $<)', + 'RULE_INPUT_NAME': '$(notdir $<)', + 'CONFIGURATION_NAME': '$(BUILDTYPE)', +} + +# Make supports multiple toolsets +generator_supports_multiple_toolsets = True + +# Request sorted dependencies in the order from dependents to dependencies. +generator_wants_sorted_dependencies = False + +# Placates pylint. +generator_additional_non_configuration_keys = [] +generator_additional_path_sections = [] +generator_extra_sources_for_rules = [] +generator_filelist_paths = None + +LINK_COMMANDS_LINUX = """\ +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)) crsT $@ $(filter %.o,$^) + +# Due to circular dependencies between libraries :(, we wrap the +# special "figure out circular dependencies" flags around the entire +# input list during linking. +quiet_cmd_link = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS) + +# We support two kinds of shared objects (.so): +# 1) shared_library, which is just bundling together many dependent libraries +# into a link line. +# 2) loadable_module, which is generating a module intended for dlopen(). +# +# They differ only slightly: +# In the former case, we want to package all dependent code into the .so. +# In the latter case, we want to package just the API exposed by the +# outermost module. +# This means shared_library uses --whole-archive, while loadable_module doesn't. +# (Note that --whole-archive is incompatible with the --start-group used in +# normal linking.) + +# Other shared-object link notes: +# - Set SONAME to the library filename so our binaries don't reference +# the local, absolute paths used on the link command-line. +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) +""" + +LINK_COMMANDS_MAC = """\ +quiet_cmd_alink = LIBTOOL-STATIC $@ +cmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool $(GYP_LIBTOOLFLAGS) -static -o $@ $(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)) -bundle $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) +""" + +LINK_COMMANDS_ANDROID = """\ +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)) crsT $@ $(filter %.o,$^) + +# Due to circular dependencies between libraries :(, we wrap the +# special "figure out circular dependencies" flags around the entire +# input list during linking. +quiet_cmd_link = LINK($(TOOLSET)) $@ +quiet_cmd_link_host = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS) +cmd_link_host = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) + +# Other shared-object link notes: +# - Set SONAME to the library filename so our binaries don't reference +# the local, absolute paths used on the link command-line. +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) +quiet_cmd_solink_module_host = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module_host = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) +""" + +LINK_COMMANDS_AIX = """\ +quiet_cmd_alink = AR($(TOOLSET)) $@ +cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) -X32_64 crs $@ $(filter %.o,$^) + +quiet_cmd_alink_thin = AR($(TOOLSET)) $@ +cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) -X32_64 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) +""" + +LINK_COMMANDS_OS390 = """\ +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)) crsT $@ $(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)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) -Wl,DLL + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) -Wl,DLL +""" + +SHARED_HEADER_MAC_COMMANDS = """ +quiet_cmd_objc = CXX($(TOOLSET)) $@ +cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< + +quiet_cmd_objcxx = CXX($(TOOLSET)) $@ +cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< + +# Commands for precompiled header files. +quiet_cmd_pch_c = CXX($(TOOLSET)) $@ +cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< +quiet_cmd_pch_cc = CXX($(TOOLSET)) $@ +cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< +quiet_cmd_pch_m = CXX($(TOOLSET)) $@ +cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< +quiet_cmd_pch_mm = CXX($(TOOLSET)) $@ +cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< + +# gyp-mac-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_mac_tool = MACTOOL $(4) $< +cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@" + +quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@ +cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4) + +quiet_cmd_infoplist = INFOPLIST $@ +cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@" +""" + +SHARED_FOOTER = """\ +# "all" is a concatenation of the "all" targets from all the included +# sub-makefiles. This is just here to clarify. +all: + +# Add in dependency-tracking rules. $(all_deps) is the list of every single +# target in our tree. Only consider the ones with .d (dependency) info: +d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) +ifneq ($(d_files),) + include $(d_files) +endif +""" + + +def WriteAutoRegenerationRule(params, root_makefile, makefile_name, build_files, Sourceify): + """Write the target to regenerate the Makefile.""" + options = params['options'] + build_files_args = [gyp.common.RelativePath(filename, options.toplevel_dir) for filename in params['build_files_arg']] + + gyp_binary = gyp.common.FixIfRelativePath(params['gyp_binary'], options.toplevel_dir) + if not gyp_binary.startswith(os.sep): + gyp_binary = os.path.join('.', gyp_binary) + + root_makefile.write( + "quiet_cmd_regen_makefile = ACTION Regenerating $@\n" + "cmd_regen_makefile = cd $(srcdir); %(cmd)s\n" + "%(makefile_name)s: %(deps)s\n" + "\t$(call do_cmd,regen_makefile)\n\n" % { + 'makefile_name': makefile_name, + 'deps': ' '.join(map(Sourceify, build_files)), + 'cmd': gyp.common.EncodePOSIXShellList([gyp_binary, '-fmake'] + gyp.RegenerateFlags(options) + build_files_args) + } + ) + + +def PerformBuild(_, configurations, params): + options = params['options'] + for config in configurations: + arguments = ['make'] + if options.toplevel_dir and options.toplevel_dir != '.': + arguments += '-C', options.toplevel_dir + arguments.append('BUILDTYPE=' + config) + print('Building [%s]: %s' % (config, arguments)) + subprocess.check_call(arguments) + + +def GenerateOutput(target_list, target_dicts, data, params): + from gyp.MakefileWriter import MakefileWriter, Sourceify, WriteRootHeaderSuffixRules, SHARED_HEADER + options = params['options'] + flavor = gyp.common.GetFlavor(params) + generator_flags = params.get('generator_flags', {}) + builddir_name = generator_flags.get('output_dir', 'out') + android_ndk_version = generator_flags.get('android_ndk_version', None) + default_target = generator_flags.get('default_target', 'all') + + def CalculateMakefilePath(build_file_arg, 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_makefile_path = gyp.common.RelativePath(os.path.dirname(build_file_arg), options.depth) + # We write the file in the base_makefile_path directory. + output_makefile = os.path.join(options.depth, base_makefile_path, base_name) + if options.generator_output: + output_makefile = os.path.join(options.depth, options.generator_output, base_makefile_path, base_name) + base_makefile_path = gyp.common.RelativePath(os.path.dirname(build_file_arg), options.toplevel_dir) + return base_makefile_path, output_makefile + + # 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 = 'Makefile' + options.suffix + makefile_path = os.path.join(options.toplevel_dir, makefile_name) + if options.generator_output: + makefile_path = os.path.join(options.toplevel_dir, options.generator_output, makefile_name) + srcdir = gyp.common.RelativePath(srcdir, options.generator_output) + Sourceify.srcdir_prefix = '$(srcdir)/' + + flock_command = 'flock' + copy_archive_arguments = '-af' + makedep_arguments = '-MMD' + header_params = { + 'default_target': default_target, + 'builddir': builddir_name, + 'default_configuration': default_configuration, + 'flock': flock_command, + 'flock_index': 1, + 'link_commands': LINK_COMMANDS_LINUX, + 'extra_commands': '', + 'srcdir': srcdir, + 'copy_archive_args': copy_archive_arguments, + 'makedep_args': makedep_arguments, + } + if flavor == 'mac': + flock_command = './gyp-mac-tool flock' + header_params.update({ + 'flock': flock_command, + 'flock_index': 2, + 'link_commands': LINK_COMMANDS_MAC, + 'extra_commands': SHARED_HEADER_MAC_COMMANDS, + }) + elif flavor == 'android': + header_params.update({ + 'link_commands': LINK_COMMANDS_ANDROID, + }) + elif flavor == 'zos': + copy_archive_arguments = '-fPR' + makedep_arguments = '-qmakedep=gcc' + header_params.update({ + 'copy_archive_args': copy_archive_arguments, + 'makedep_args': makedep_arguments, + 'link_commands': LINK_COMMANDS_OS390, + }) + elif flavor == 'solaris': + header_params.update({ + 'flock': './gyp-flock-tool flock', + 'flock_index': 2, + }) + elif flavor == 'freebsd': + # Note: OpenBSD has sysutils/flock. lockf seems to be FreeBSD specific. + header_params.update({ + 'flock': 'lockf', + }) + elif flavor == 'openbsd': + copy_archive_arguments = '-pPRf' + header_params.update({ + 'copy_archive_args': copy_archive_arguments, + }) + elif flavor == 'aix': + copy_archive_arguments = '-pPRf' + header_params.update({ + 'copy_archive_args': copy_archive_arguments, + 'link_commands': LINK_COMMANDS_AIX, + 'flock': './gyp-flock-tool flock', + 'flock_index': 2, + }) + + header_params.update({ + 'CC.target': GetEnvironFallback(('CC_target', 'CC'), '$(CC)'), + 'AR.target': GetEnvironFallback(('AR_target', 'AR'), '$(AR)'), + 'CXX.target': GetEnvironFallback(('CXX_target', 'CXX'), '$(CXX)'), + 'LINK.target': GetEnvironFallback(('LINK_target', 'LINK'), '$(LINK)'), + 'CC.host': GetEnvironFallback(('CC_host',), 'cc'), + 'AR.host': GetEnvironFallback(('AR_host',), 'ar'), + 'CXX.host': GetEnvironFallback(('CXX_host',), 'c++'), + 'LINK.host': GetEnvironFallback(('LINK_host',), '$(CXX.host)'), + }) + + build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) + make_global_settings_array = data[build_file].get('make_global_settings', []) + wrappers = {} + for key, value in make_global_settings_array: + if key.endswith('_wrapper'): + wrappers[key[:-len('_wrapper')]] = '$(abspath %s)' % value + make_global_settings = '' + for key, value in make_global_settings_array: + if re.match('.*_wrapper', key): + continue + if value[0] != '$': + value = '$(abspath %s)' % value + wrapper = wrappers.get(key) + if wrapper: + value = '%s %s' % (wrapper, value) + del wrappers[key] + if key in ('CC', 'CC.host', 'CXX', 'CXX.host'): + make_global_settings += 'ifneq (,$(filter $(origin %s), undefined default))\n' % key + # Let gyp-time envvars win over global settings. + 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: + make_global_settings += '%s ?= %s\n' % (key, value) + # TODO(ukai): define cmd when only wrapper is specified in + # make_global_settings. + + header_params['make_global_settings'] = make_global_settings + + 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 + # could be different. + if android_ndk_version: + root_makefile.write( + '# Define LOCAL_PATH for build of Android applications.\n' + 'LOCAL_PATH := $(call my-dir)\n' + '\n' + ) + for toolset in toolsets: + root_makefile.write('TOOLSET := %s\n' % toolset) + WriteRootHeaderSuffixRules(root_makefile) + + # Put build-time support tools next to the root Makefile. + dest_path = os.path.dirname(makefile_path) + gyp.common.CopyTool(flavor, dest_path) + + # 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() + writer = None + for qualified_target in target_list: + build_file, target, toolset = gyp.common.ParseQualifiedTarget(qualified_target) + + 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. %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'] + 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'] + + if flavor == 'mac': + gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec) + + writer = MakefileWriter(generator_flags, flavor) + writer.Write(qualified_target, base_path, output_file, spec, configs, part_of_all=qualified_target in needed_targets) + + # 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) + + assert writer + # Write out per-gyp (sub-project) Makefiles. + depth_rel_path = gyp.common.RelativePath(options.depth, os.getcwd()) + for build_file in build_files: + # The paths in build_files were relativized above, so undo that before + # testing against the non-relativized items in target_list and before + # calculating the Makefile path. + build_file_path = os.path.join(depth_rel_path, build_file) + related_gyp_targets = [t for t in target_list if t.startswith(build_file) and t in needed_targets] + # Only generate Makefiles for gyp files with targets. + if not related_gyp_targets: + continue + build_file_name = "%s.Makefile" % os.path.splitext(os.path.basename(build_file))[0] + _, submake_output_file = CalculateMakefilePath(build_file_path, build_file_name) + makefile_rel_path = gyp.common.RelativePath(os.path.dirname(makefile_path), os.path.dirname(submake_output_file)) + gyp_targets_names = [target_dicts[t]['target_name'] for t in related_gyp_targets] + writer.WriteSubMake(submake_output_file, makefile_rel_path, gyp_targets_names, builddir_name) + + # Write out the sorted list of includes. + root_makefile.write('\n') + for include_file in sorted(include_list): + # We wrap each .mk include in an if statement so users can tell make to + # not load a file by setting NO_LOAD. The below make code says, only + # load the .mk file if the .mk filename doesn't start with a token in + # NO_LOAD. + include_conditional_tmpl="""\ +ifeq ($(strip $(foreach prefix,$(NO_LOAD), $(findstring $(join ^,$(prefix)), $(join ^,%(include_file)s)))),) + include %(include_file)s +endif +""" + root_makefile.write(include_conditional_tmpl % { 'include_file': include_file }) + root_makefile.write('\n') + + if (not generator_flags.get('standalone') + and generator_flags.get('auto_regeneration', True)): + WriteAutoRegenerationRule(params, root_makefile, makefile_name, build_files, Sourceify) + + root_makefile.write(SHARED_FOOTER) + + root_makefile.close() + + +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') + default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib') + default_variables.setdefault('SHARED_LIB_DIR', generator_default_variables['PRODUCT_DIR']) + default_variables.setdefault('LIB_DIR', generator_default_variables['PRODUCT_DIR']) + + # Copy additional generator configuration data from Xcode, which is shared + # by the Mac Make generator. + import gyp.generator.xcode as xcode_generator + global generator_additional_non_configuration_keys + generator_additional_non_configuration_keys = getattr(xcode_generator, 'generator_additional_non_configuration_keys', []) + global generator_additional_path_sections + generator_additional_path_sections = getattr(xcode_generator, 'generator_additional_path_sections', []) + global generator_extra_sources_for_rules + generator_extra_sources_for_rules = getattr(xcode_generator, 'generator_extra_sources_for_rules', []) + else: + operating_system = flavor + if flavor == 'android': + operating_system = 'linux' # Keep this legacy behavior for now. + default_variables.setdefault('OS', operating_system) + if flavor == 'aix': + default_variables.setdefault('SHARED_LIB_SUFFIX', '.a') + else: + default_variables.setdefault('SHARED_LIB_SUFFIX', '.so') + default_variables.setdefault('SHARED_LIB_DIR', '$(builddir)/lib.$(TOOLSET)') + default_variables.setdefault('LIB_DIR', '$(obj).$(TOOLSET)') + + +def CalculateGeneratorInputInfo(params): + """Calculate the generator specific info that gets fed to input (called by + gyp).""" + generator_flags = params.get('generator_flags', {}) + android_ndk_version = generator_flags.get('android_ndk_version', None) + # Android NDK requires a strict link order. + if android_ndk_version: + 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')) + + global generator_filelist_paths + generator_filelist_paths = { + 'toplevel': params['options'].toplevel_dir, + 'qualified_out_dir': qualified_out_dir, + } diff --git a/tools/gyp/pylib/gyp/generator/msvs.py b/tools/gyp/gyp/generator/msvs.py similarity index 77% rename from tools/gyp/pylib/gyp/generator/msvs.py rename to tools/gyp/gyp/generator/msvs.py index dbde9e279eb5d6..6e798ad1b8a4b5 100644 --- a/tools/gyp/pylib/gyp/generator/msvs.py +++ b/tools/gyp/gyp/generator/msvs.py @@ -2,7 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import copy +from __future__ import print_function + +from collections import OrderedDict import ntpath import os import posixpath @@ -10,28 +12,12 @@ import subprocess import sys -import gyp.common +import gyp.common as 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 -import gyp.MSVSToolFile as MSVSToolFile -import gyp.MSVSUserFile as MSVSUserFile -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() +import gyp.MSVS as MSVS +from gyp.MSVS import MSVSNew, MSVSSettings, MSVSToolFile, MSVSVersion +from gyp.common import GypError, OrderedSet # Regular expression for validating Visual Studio GUIDs. If the GUID @@ -114,7 +100,7 @@ def _import_OrderedDict(): # 64-bit. def _GetDomainAndUserName(): if sys.platform not in ('win32', 'cygwin'): - return ('DOMAIN', 'USERNAME') + return 'DOMAIN', 'USERNAME' global cached_username global cached_domain if not cached_domain or not cached_username: @@ -134,9 +120,7 @@ def _GetDomainAndUserName(): domain = domain_match.group(1) cached_domain = domain cached_username = username - return (cached_domain, cached_username) - -fixpath_prefix = None + return cached_domain, cached_username def _NormalizedSource(source): @@ -157,6 +141,8 @@ def _NormalizedSource(source): return source +fixpath_prefix = '' + def _FixPath(path): """Convert paths to a form that will make sense in a vcproj file. @@ -179,8 +165,7 @@ def _FixPaths(paths): return [_FixPath(i) for i in paths] -def _ConvertSourcesToFilterHierarchy(sources, prefix=None, excluded=None, - list_excluded=True, msvs_version=None): +def _ConvertSourcesToFilterHierarchy(sources, prefix=None, excluded=None, list_excluded=True, msvs_version=None): """Converts a list split source file paths into a vcproj folder hierarchy. Arguments: @@ -211,35 +196,32 @@ def _ConvertSourcesToFilterHierarchy(sources, prefix=None, excluded=None, excluded_result.append(filename) else: result.append(filename) - elif msvs_version and not msvs_version.UsesVcxproj(): + elif msvs_version and not msvs_version.uses_vcxproj: # 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) + contents = _ConvertSourcesToFilterHierarchy( + [s[1:]], prefix + [s[0]], excluded=excluded, list_excluded=list_excluded, msvs_version=msvs_version + ) + contents = MSVS.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) + excluded_folder = MSVS.Filter('_excluded_files', contents=excluded_result) result.append(excluded_folder) - if msvs_version and msvs_version.UsesVcxproj(): + if msvs_version and msvs_version.uses_vcxproj: return result # Populate all the folders. for f in folders: - contents = _ConvertSourcesToFilterHierarchy(folders[f], prefix=prefix + [f], - excluded=excluded, - list_excluded=list_excluded, - msvs_version=msvs_version) - contents = MSVSProject.Filter(f, contents=contents) + contents = _ConvertSourcesToFilterHierarchy( + folders[f], prefix=prefix + [f], excluded=excluded, list_excluded=list_excluded, msvs_version=msvs_version + ) + contents = MSVS.Filter(f, contents=contents) result.append(contents) return result @@ -267,9 +249,8 @@ def _ToolSetOrAppend(tools, tool_name, setting, value, only_if_unset=False): tool[setting] += value else: raise TypeError( - 'Appending "%s" to a non-list setting "%s" for tool "%s" is ' - 'not allowed, previous value: %s' % ( - value, setting, tool_name, str(tool[setting]))) + 'Appending "%s" to a non-list setting "%s" for tool "%s" is not allowed, previous value: %s' % (value, setting, tool_name, str(tool[setting])) + ) else: tool[setting] = value @@ -294,42 +275,14 @@ def _ConfigFullName(config_name, config_data): return '%s|%s' % (_ConfigBaseName(config_name, platform_name), platform_name) -def _ConfigWindowsTargetPlatformVersion(config_data, version): - config_ver = config_data.get('msvs_windows_sdk_version') - vers = [config_ver] if config_ver else version.compatible_sdks - for ver in vers: - for key in [ - r'HKLM\Software\Microsoft\Microsoft SDKs\Windows\%s', - r'HKLM\Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows\%s']: - sdk_dir = MSVSVersion._RegistryGetValue(key % ver, 'InstallationFolder') - if not sdk_dir: - continue - version = MSVSVersion._RegistryGetValue(key % ver, 'ProductVersion') or '' - # Find a matching entry in sdk_dir\include. - expected_sdk_dir=r'%s\include' % sdk_dir - names = sorted([x for x in (os.listdir(expected_sdk_dir) - if os.path.isdir(expected_sdk_dir) - else [] - ) - if x.startswith(version)], reverse=True) - if names: - return names[0] - else: - print >> sys.stdout, ( - 'Warning: No include files found for ' - 'detected Windows SDK version %s' % (version) - ) - - -def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path, - quote_cmd, do_setup_env): +def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path, quote_cmd, do_setup_env): if [x for x in cmd if '$(InputDir)' in x]: input_dir_preamble = ( 'set INPUTDIR=$(InputDir)\n' 'if NOT DEFINED INPUTDIR set INPUTDIR=.\\\n' 'set INPUTDIR=%INPUTDIR:~0,-1%\n' - ) + ) else: input_dir_preamble = '' @@ -338,18 +291,13 @@ def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path, cygwin_dir = _FixPath(spec.get('msvs_cygwin_dirs', ['.'])[0]) # Prepare command. direct_cmd = cmd - direct_cmd = [i.replace('$(IntDir)', - '`cygpath -m "${INTDIR}"`') for i in direct_cmd] - direct_cmd = [i.replace('$(OutDir)', - '`cygpath -m "${OUTDIR}"`') for i in direct_cmd] - direct_cmd = [i.replace('$(InputDir)', - '`cygpath -m "${INPUTDIR}"`') for i in direct_cmd] + direct_cmd = [i.replace('$(IntDir)', '`cygpath -m "${INTDIR}"`') for i in direct_cmd] + direct_cmd = [i.replace('$(OutDir)', '`cygpath -m "${OUTDIR}"`') for i in direct_cmd] + direct_cmd = [i.replace('$(InputDir)', '`cygpath -m "${INPUTDIR}"`') for i in direct_cmd] if has_input_path: - direct_cmd = [i.replace('$(InputPath)', - '`cygpath -m "${INPUTPATH}"`') - for i in direct_cmd] + direct_cmd = [i.replace('$(InputPath)', '`cygpath -m "${INPUTPATH}"`') for i in direct_cmd] direct_cmd = ['\\"%s\\"' % i.replace('"', '\\\\\\"') for i in direct_cmd] - # direct_cmd = gyp.common.EncodePOSIXShellList(direct_cmd) + # direct_cmd = common.EncodePOSIXShellList(direct_cmd) direct_cmd = ' '.join(direct_cmd) # TODO(quote): regularize quoting path names throughout the module cmd = '' @@ -365,8 +313,7 @@ def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path, if has_input_path and direct_cmd.find('INPUTPATH') >= 0: cmd += 'set INPUTPATH=$(InputPath) && ' cmd += 'bash -c "%(cmd)s"' - cmd = cmd % {'cygwin_dir': cygwin_dir, - 'cmd': direct_cmd} + cmd = cmd % {'cygwin_dir': cygwin_dir, 'cmd': direct_cmd} return input_dir_preamble + cmd else: # Convert cat --> type to mimic unix. @@ -407,8 +354,7 @@ def _BuildCommandLineForRule(spec, rule, has_input_path, do_setup_env): elif isinstance(mcs, str): mcs = int(mcs) quote_cmd = int(rule.get('msvs_quote_cmd', 1)) - return _BuildCommandLineForRuleRaw(spec, rule['action'], mcs, has_input_path, - quote_cmd, do_setup_env=do_setup_env) + return _BuildCommandLineForRuleRaw(spec, rule['action'], mcs, has_input_path, quote_cmd, do_setup_env=do_setup_env) def _AddActionStep(actions_dict, inputs, outputs, description, command): @@ -446,8 +392,7 @@ def _AddActionStep(actions_dict, inputs, outputs, description, command): actions_dict[chosen_input].append(action) -def _AddCustomBuildToolForMSVS(p, spec, primary_input, - inputs, outputs, description, cmd): +def _AddCustomBuildToolForMSVS(p, spec, primary_input, inputs, outputs, description, cmd): """Add a custom build tool to execute something. Arguments: @@ -461,17 +406,18 @@ def _AddCustomBuildToolForMSVS(p, spec, primary_input, """ inputs = _FixPaths(inputs) outputs = _FixPaths(outputs) - tool = MSVSProject.Tool( - 'VCCustomBuildTool', - {'Description': description, - 'AdditionalDependencies': ';'.join(inputs), - 'Outputs': ';'.join(outputs), - 'CommandLine': cmd, - }) + tool = MSVS.Tool( + 'VCCustomBuildTool', + { + 'Description': description, + 'AdditionalDependencies': ';'.join(inputs), + 'Outputs': ';'.join(outputs), + 'CommandLine': cmd, + } + ) # Add to the properties of primary input for each config. - for config_name, c_data in spec['configurations'].iteritems(): - p.AddFileConfig(_FixPath(primary_input), - _ConfigFullName(config_name, c_data), tools=[tool]) + for config_name, c_data in spec['configurations'].items(): + p.AddFileConfig(_FixPath(primary_input), _ConfigFullName(config_name, c_data), tools=[tool]) def _AddAccumulatedActionsToMSVS(p, spec, actions_dict): @@ -513,16 +459,16 @@ def _RuleExpandPath(path, input_file): Returns: The string substituted path. """ - path = path.replace('$(InputName)', - os.path.splitext(os.path.split(input_file)[1])[0]) + path = path.replace('$(InputName)', os.path.splitext(os.path.split(input_file)[1])[0]) path = path.replace('$(InputDir)', os.path.dirname(input_file)) - path = path.replace('$(InputExt)', - os.path.splitext(os.path.split(input_file)[1])[1]) + path = path.replace('$(InputExt)', os.path.splitext(os.path.split(input_file)[1])[1]) path = path.replace('$(InputFileName)', os.path.split(input_file)[1]) path = path.replace('$(InputPath)', input_file) return path +# TODO(refack): Figure out whats up here +# noinspection PyUnusedLocal def _FindRuleTriggerFiles(rule, sources): """Find the list of files which a particular rule applies to. @@ -553,7 +499,7 @@ def _RuleInputsAndOutputs(rule, trigger_file): inputs.add(_RuleExpandPath(i, trigger_file)) for o in raw_outputs: outputs.add(_RuleExpandPath(o, trigger_file)) - return (inputs, outputs) + return inputs, outputs def _GenerateNativeRulesForMSVS(p, rules, output_dir, spec, options): @@ -613,7 +559,7 @@ def _GenerateExternalRules(rules, output_dir, spec, actions_to_add: The list of actions we will add to. """ filename = '%s_rules%s.mk' % (spec['target_name'], options.suffix) - mk_file = gyp.common.WriteOnDiff(os.path.join(output_dir, filename)) + mk_file = common.WriteOnDiff(os.path.join(output_dir, filename)) # Find cygwin style versions of some paths. mk_file.write('OutDirCygwin:=$(shell cygpath -u "$(OutDir)")\n') mk_file.write('IntDirCygwin:=$(shell cygpath -u "$(IntDir)")\n') @@ -721,7 +667,7 @@ def _Replace(match): # For a literal quote, CommandLineToArgv requires an odd number of # backslashes preceding it, and it produces half as many literal backslashes # (rounded down). So we need to produce 2n+1 backslashes. - return 2 * match.group(1) + '\\"' + return str(2 * match.group(1)) + '\\"' # Escape all quotes so that they are interpreted literally. s = quote_replacer_regex.sub(_Replace, s) @@ -759,7 +705,7 @@ def _Replace(match): # For a non-literal quote, CommandLineToArgv requires an even number of # backslashes preceding it, and it produces half as many literal # backslashes. So we need to produce 2n backslashes. - return 2 * match.group(1) + '"' + match.group(2) + '"' + return str(2 * match.group(1)) + '"' + str(match.group(2)) + '"' segments = s.split('"') # The unquoted segments are at the even-numbered indices. @@ -775,8 +721,8 @@ def _Replace(match): # the VCProj but cause the same problem on the final command-line. Moving # the item to the end of the list does works, but that's only possible if # there's only one such item. Let's just warn the user. - print >> sys.stderr, ('Warning: MSVS may misinterpret the odd number of ' + - 'quotes in ' + s) + print(('Warning: MSVS may misinterpret the odd number of ' + + 'quotes in ' + s), file=sys.stderr) return s @@ -798,7 +744,7 @@ def _EscapeCommandLineArgumentForMSBuild(s): """Escapes a Windows command-line argument for use by MSBuild.""" def _Replace(match): - return (len(match.group(1)) / 2 * 4) * '\\' + '\\"' + return str('\\' * (len(match.group(1)) // 2 * 4)) + '\\"' # Escape all quotes so that they are interpreted literally. s = quote_replacer_regex2.sub(_Replace, s) @@ -898,11 +844,11 @@ def _GetDefaultConfiguration(spec): return spec['configurations'][spec['default_configuration']] -def _GetGuidOfProject(proj_path, spec): - """Get the guid for the project. +def _TryGetGuidOfProject(spec): + """ + Get the guid for the project. Arguments: - proj_path: Path of the vcproj or vcxproj file to generate. spec: The target dictionary containing the properties of the target. Returns: the guid. @@ -915,18 +861,15 @@ def _GetGuidOfProject(proj_path, spec): guid = default_config.get('msvs_guid') if guid: if VALID_MSVS_GUID_CHARS.match(guid) is None: - raise ValueError('Invalid MSVS guid: "%s". Must match regex: "%s".' % - (guid, VALID_MSVS_GUID_CHARS.pattern)) + raise ValueError('Invalid MSVS guid: "%s". Must match regex: "%s".' % (guid, VALID_MSVS_GUID_CHARS.pattern)) guid = '{%s}' % guid - guid = guid or MSVSNew.MakeGuid(proj_path) return guid -def _GetMsbuildToolsetOfProject(proj_path, spec, version): +def _GetMsbuildToolsetOfProject(spec, version): """Get the platform toolset for the project. Arguments: - proj_path: Path of the vcproj or vcxproj file to generate. spec: The target dictionary containing the properties of the target. version: The MSVSVersion object. Returns: @@ -934,9 +877,7 @@ def _GetMsbuildToolsetOfProject(proj_path, spec, version): """ # Pluck out the default configuration. default_config = _GetDefaultConfiguration(spec) - toolset = default_config.get('msbuild_toolset') - if not toolset and version.DefaultToolset(): - toolset = version.DefaultToolset() + toolset = default_config.get('msbuild_toolset', version.default_toolset) if spec['type'] == 'windows_driver': toolset = 'WindowsKernelModeDriver10.0' return toolset @@ -959,116 +900,7 @@ def _GenerateProject(project, options, version, generator_flags): if default_config.get('msvs_existing_vcproj'): return [] - if version.UsesVcxproj(): - return _GenerateMSBuildProject(project, options, version, generator_flags) - else: - 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. - - Arguments: - project: The project object we will generate the file for. - options: Global options passed to the generator. - version: The VisualStudioVersion object. - generator_flags: dict of generator-specific flags. - """ - spec = project.spec - gyp.common.EnsureDirExists(project.path) - - platforms = _GetUniquePlatforms(spec) - p = MSVSProject.Writer(project.path, version, spec['target_name'], - project.guid, platforms) - - # Get directory project file is in. - project_dir = os.path.split(project.path)[0] - gyp_path = _NormalizedSource(project.build_file) - relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, project_dir) - - config_type = _GetMSVSConfigurationType(spec, project.build_file) - 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, - gyp_file) - - # Add rules. - actions_to_add = {} - _GenerateRulesForMSVS(p, project_dir, options, spec, - sources, excluded_sources, - 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, version)) - - # Add in files. - missing_sources = _VerifySourcesExist(sources, project_dir) - p.AddFiles(sources) - - _AddToolFilesToMSVS(p, spec) - _HandlePreCompiledHeaders(p, sources, spec) - _AddActions(actions_to_add, spec, relative_path_of_gyp_file) - _AddCopies(actions_to_add, spec) - _WriteMSVSUserFile(project.path, version, spec) - - # NOTE: this stanza must appear after all actions have been decided. - # Don't excluded sources with actions attached, or they won't run. - excluded_sources = _FilterActionsFromExcluded( - excluded_sources, actions_to_add) - _ExcludeFilesFromBeingBuilt(p, spec, excluded_sources, excluded_idl, - list_excluded) - _AddAccumulatedActionsToMSVS(p, spec, actions_to_add) - - # Write it out. - p.WriteIfChanged() - - return missing_sources + return _GenerateMSBuildProject(project, options, version, generator_flags) def _GetUniquePlatforms(spec): @@ -1087,24 +919,6 @@ def _GetUniquePlatforms(spec): return platforms -def _CreateMSVSUserFile(proj_path, version, spec): - """Generates a .user file for the user running this Gyp program. - - Arguments: - proj_path: The path of the project file being created. The .user file - shares the same path (with an appropriate suffix). - version: The VisualStudioVersion object. - spec: The target dictionary containing the properties of the target. - Returns: - The MSVSUserFile object created. - """ - (domain, username) = _GetDomainAndUserName() - vcuser_filename = '.'.join([proj_path, domain, username, 'user']) - user_file = MSVSUserFile.Writer(vcuser_filename, version, - spec['target_name']) - return user_file - - def _GetMSVSConfigurationType(spec, build_file): """Returns the configuration type for this project. @@ -1136,93 +950,6 @@ def _GetMSVSConfigurationType(spec, build_file): return config_type -def _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config): - """Adds a configuration to the MSVS project. - - Many settings in a vcproj file are specific to a configuration. This - function the main part of the vcproj file that's configuration specific. - - Arguments: - p: The target project being generated. - spec: The target dictionary containing the properties of the target. - config_type: The configuration type, a number as defined by Microsoft. - config_name: The name of the configuration. - config: The dictionary that defines the special processing to be done - for this configuration. - """ - # Get the information for this configuration - 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) - defines = _GetDefines(config) - defines = [_EscapeCppDefineForMSVS(d) for d in defines] - disabled_warnings = _GetDisabledWarnings(config) - prebuild = config.get('msvs_prebuild') - postbuild = config.get('msvs_postbuild') - def_file = _GetModuleDefinition(spec) - precompiled_header = config.get('msvs_precompiled_header') - - # Prepare the list of tools as a dictionary. - tools = dict() - # Add in user specified msvs_settings. - msvs_settings = config.get('msvs_settings', {}) - MSVSSettings.ValidateMSVSSettings(msvs_settings) - - # Prevent default library inheritance from the environment. - _ToolAppend(tools, 'VCLinkerTool', 'AdditionalDependencies', ['$(NOINHERIT)']) - - for tool in msvs_settings: - settings = config['msvs_settings'][tool] - for setting in settings: - _ToolAppend(tools, tool, setting, settings[setting]) - # 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. - _ToolAppend(tools, 'VCLinkerTool', 'AdditionalDependencies', libraries) - _ToolAppend(tools, 'VCLinkerTool', 'AdditionalLibraryDirectories', - library_dirs) - if out_file: - _ToolAppend(tools, vc_tool, 'OutputFile', out_file, only_if_unset=True) - # Add defines. - _ToolAppend(tools, 'VCCLCompilerTool', 'PreprocessorDefinitions', defines) - _ToolAppend(tools, 'VCResourceCompilerTool', 'PreprocessorDefinitions', - defines) - # Change program database directory to prevent collisions. - _ToolAppend(tools, 'VCCLCompilerTool', 'ProgramDataBaseFileName', - '$(IntDir)$(ProjectName)\\vc80.pdb', only_if_unset=True) - # Add disabled warnings. - _ToolAppend(tools, 'VCCLCompilerTool', - 'DisableSpecificWarnings', disabled_warnings) - # Add Pre-build. - _ToolAppend(tools, 'VCPreBuildEventTool', 'CommandLine', prebuild) - # Add Post-build. - _ToolAppend(tools, 'VCPostBuildEventTool', 'CommandLine', postbuild) - # Turn on precompiled headers if appropriate. - if precompiled_header: - precompiled_header = os.path.split(precompiled_header)[1] - _ToolAppend(tools, 'VCCLCompilerTool', 'UsePrecompiledHeader', '2') - _ToolAppend(tools, 'VCCLCompilerTool', - 'PrecompiledHeaderThrough', precompiled_header) - _ToolAppend(tools, 'VCCLCompilerTool', - 'ForcedIncludeFiles', precompiled_header) - # Loadable modules don't generate import libraries; - # tell dependent projects to not expect one. - if spec['type'] == 'loadable_module': - _ToolAppend(tools, 'VCLinkerTool', 'IgnoreImportLibrary', 'true') - # Set the module definition file if any. - if def_file: - _ToolAppend(tools, 'VCLinkerTool', 'ModuleDefinitionFile', def_file) - - _AddConfigurationToMSVS(p, spec, tools, config, config_type, config_name) - - def _GetIncludeDirs(config): """Returns the list of directories to be used for #include directives. @@ -1278,7 +1005,7 @@ def _GetLibraries(spec): found = OrderedSet() unique_libraries_list = [] for entry in reversed(libraries): - library = re.sub(r'^\-l', '', entry) + library = re.sub(r'^-l', '', entry) if not os.path.splitext(library)[1]: library += '.lib' if library not in found: @@ -1392,10 +1119,10 @@ def _ConvertToolsToExpectedForm(tools): A list of Tool objects. """ tool_list = [] - for tool, settings in tools.iteritems(): + for tool, settings in tools.items(): # Collapse settings with lists. settings_fixed = {} - for setting, value in settings.iteritems(): + for setting, value in settings.items(): if type(value) == list: if ((tool == 'VCLinkerTool' and setting == 'AdditionalDependencies') or @@ -1406,30 +1133,28 @@ def _ConvertToolsToExpectedForm(tools): else: settings_fixed[setting] = value # Add in this tool. - tool_list.append(MSVSProject.Tool(tool, settings_fixed)) + tool_list.append(MSVS.Tool(tool, settings_fixed)) return tool_list -def _AddConfigurationToMSVS(p, spec, tools, config, config_type, config_name): - """Add to the project file the configuration specified by config. +def _AddConfigurationToMSVS(p, tools, config, config_type, config_name): + """ + Add to the project file the configuration specified by config. Arguments: p: The target project being generated. - spec: the target project dict. tools: A dictionary of settings; the tool name is the key. - config: The dictionary that defines the special processing to be done - for this configuration. + config: The dictionary that defines the special processing to be done for this configuration. config_type: The configuration type, a number as defined by Microsoft. config_name: The name of the configuration. """ - attributes = _GetMSVSAttributes(spec, config, config_type) + attributes = _GetMSVSAttributes(config, config_type) # Add in this configuration. tool_list = _ConvertToolsToExpectedForm(tools) - p.AddConfig(_ConfigFullName(config_name, config), - attrs=attributes, tools=tool_list) + p.AddConfig(_ConfigFullName(config_name, config), attrs=attributes, tools=tool_list) -def _GetMSVSAttributes(spec, config, config_type): +def _GetMSVSAttributes(config, config_type): # Prepare configuration attributes. prepared_attrs = {} source_attrs = config.get('msvs_configuration_attributes', {}) @@ -1442,8 +1167,7 @@ def _GetMSVSAttributes(spec, config, config_type): prepared_attrs['InheritedPropertySheets'] = ';'.join(vsprops_dirs) # Set configuration type. prepared_attrs['ConfigurationType'] = config_type - output_dir = prepared_attrs.get('OutputDirectory', - '$(SolutionDir)$(ConfigurationName)') + output_dir = prepared_attrs.get('OutputDirectory', '$(SolutionDir)$(ConfigurationName)') prepared_attrs['OutputDirectory'] = _FixPath(output_dir) + '\\' if 'IntermediateDirectory' not in prepared_attrs: intermediate = '$(ConfigurationName)\\obj\\$(ProjectName)' @@ -1456,7 +1180,9 @@ def _GetMSVSAttributes(spec, config, config_type): def _AddNormalizedSources(sources_set, sources_array): - sources_set.update(_NormalizedSource(s) for s in sources_array) + sources_list = [_NormalizedSource(s) for s in sources_array] + sources_list = sorted(sources_list, key=lambda s: os.path.basename(s)) + sources_set.update(sources_list) def _PrepareListOfSources(spec, generator_flags, gyp_file): @@ -1495,19 +1221,16 @@ def _PrepareListOfSources(spec, generator_flags, gyp_file): # Add in 'copies' inputs and outputs. for cpy in spec.get('copies', []): _AddNormalizedSources(sources, cpy.get('files', [])) - return (sources, excluded_sources) + return sources, excluded_sources -def _AdjustSourcesAndConvertToFilterHierarchy( - spec, options, gyp_dir, sources, excluded_sources, list_excluded, version): +def _AdjustSourcesAndConvertToFilterHierarchy(spec, sources, excluded_sources, list_excluded, version): """Adjusts the list of sources and excluded sources. Also converts the sets to lists. Arguments: spec: The target dictionary containing the properties of the target. - options: Global generator options. - 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. @@ -1534,19 +1257,17 @@ def _AdjustSourcesAndConvertToFilterHierarchy( # Convert to folders and the right slashes. sources = [i.split('\\') for i in sources] - sources = _ConvertSourcesToFilterHierarchy(sources, excluded=fully_excluded, - list_excluded=list_excluded, - msvs_version=version) + sources = _ConvertSourcesToFilterHierarchy(sources, excluded=fully_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]) \ + if version.uses_vcxproj: + while all([isinstance(s, MSVS.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): + while len(sources) == 1 and isinstance(sources[0], MSVS.Filter): sources = sources[0].contents return sources, excluded_sources, excluded_idl @@ -1570,7 +1291,7 @@ def _IdlFilesHandledNonNatively(spec, sources): def _GetPrecompileRelatedFiles(spec): # Gather a list of precompiled header related sources. precompiled_related = [] - for _, config in spec['configurations'].iteritems(): + for _, config in spec['configurations'].items(): for k in precomp_keys: f = config.get(k) if f: @@ -1581,7 +1302,7 @@ def _GetPrecompileRelatedFiles(spec): def _ExcludeFilesFromBeingBuilt(p, spec, excluded_sources, excluded_idl, list_excluded): exclusions = _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl) - for file_name, excluded_configs in exclusions.iteritems(): + for file_name, excluded_configs in exclusions.items(): if (not list_excluded and len(excluded_configs) == len(spec['configurations'])): # If we're not listing excluded files, then they won't appear in the @@ -1598,7 +1319,7 @@ def _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl): # Exclude excluded sources from being built. for f in excluded_sources: excluded_configs = [] - for config_name, config in spec['configurations'].iteritems(): + for config_name, config in spec['configurations'].items(): precomped = [_FixPath(config.get(i, '')) for i in precomp_keys] # Don't do this for ones that are precompiled header related. if f not in precomped: @@ -1608,7 +1329,7 @@ def _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl): # Exclude them now. for f in excluded_idl: excluded_configs = [] - for config_name, config in spec['configurations'].iteritems(): + for config_name, config in spec['configurations'].items(): excluded_configs.append((config_name, config)) exclusions[f] = excluded_configs return exclusions @@ -1617,7 +1338,7 @@ def _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl): def _AddToolFilesToMSVS(p, spec): # Add in tool files (rules). tool_files = OrderedSet() - for _, config in spec['configurations'].iteritems(): + for _, config in spec['configurations'].items(): for f in config.get('msvs_tool_files', []): tool_files.add(f) for f in tool_files: @@ -1630,34 +1351,30 @@ def _HandlePreCompiledHeaders(p, sources, spec): # kind (i.e. C vs. C++) as the precompiled header source stub needs # to have use of precompiled headers disabled. extensions_excluded_from_precompile = [] - for config_name, config in spec['configurations'].iteritems(): + for config_name, config in spec['configurations'].items(): source = config.get('msvs_precompiled_source') if source: source = _FixPath(source) # UsePrecompiledHeader=1 for if using precompiled headers. - tool = MSVSProject.Tool('VCCLCompilerTool', - {'UsePrecompiledHeader': '1'}) - p.AddFileConfig(source, _ConfigFullName(config_name, config), - {}, tools=[tool]) + tool = MSVS.Tool('VCCLCompilerTool', {'UsePrecompiledHeader': '1'}) + p.AddFileConfig(source, _ConfigFullName(config_name, config), {}, tools=[tool]) basename, extension = os.path.splitext(source) if extension == '.c': extensions_excluded_from_precompile = ['.cc', '.cpp', '.cxx'] else: extensions_excluded_from_precompile = ['.c'] + def DisableForSourceTree(source_tree): - for source in source_tree: - if isinstance(source, MSVSProject.Filter): - DisableForSourceTree(source.contents) + for source2 in source_tree: + if isinstance(source2, MSVS.Filter): + DisableForSourceTree(source2.contents) else: - basename, extension = os.path.splitext(source) - if extension in extensions_excluded_from_precompile: - for config_name, config in spec['configurations'].iteritems(): - tool = MSVSProject.Tool('VCCLCompilerTool', - {'UsePrecompiledHeader': '0', - 'ForcedIncludeFiles': '$(NOINHERIT)'}) - p.AddFileConfig(_FixPath(source), - _ConfigFullName(config_name, config), - {}, tools=[tool]) + basename2, extension2 = os.path.splitext(source2) + if extension2 in extensions_excluded_from_precompile: + for config_name2, config2 in spec['configurations'].items(): + tool2 = MSVS.Tool('VCCLCompilerTool', {'UsePrecompiledHeader': '0', 'ForcedIncludeFiles': '$(NOINHERIT)'}) + p.AddFileConfig(_FixPath(source2), _ConfigFullName(config_name2, config2), {}, tools=[tool2]) + # Do nothing if there was no precompiled source. if extensions_excluded_from_precompile: DisableForSourceTree(sources) @@ -1687,27 +1404,6 @@ def _AddActions(actions_to_add, spec, relative_path_of_gyp_file): command=cmd) -def _WriteMSVSUserFile(project_path, version, spec): - # Add run_as and test targets. - if 'run_as' in spec: - run_as = spec['run_as'] - action = run_as.get('action', []) - environment = run_as.get('environment', []) - working_directory = run_as.get('working_directory', '.') - elif int(spec.get('test', 0)): - action = ['$(TargetPath)', '--gtest_print_time'] - environment = [] - working_directory = '.' - else: - return # Nothing to add - # Write out the user file. - user_file = _CreateMSVSUserFile(project_path, version, spec) - for config_name, c_data in spec['configurations'].iteritems(): - user_file.AddDebugSettings(_ConfigFullName(config_name, c_data), - action, environment, working_directory) - user_file.WriteIfChanged() - - def _AddCopies(actions_to_add, spec): copies = _GetCopies(spec) for inputs, outputs, cmd, description in copies: @@ -1756,16 +1452,16 @@ def _GetPathDict(root, path): def _DictsToFolders(base_path, bucket, flat): # Convert to folders recursively. children = [] - for folder, contents in bucket.iteritems(): + for folder, contents in bucket.items(): if type(contents) == dict: folder_children = _DictsToFolders(os.path.join(base_path, folder), contents, flat) if flat: children += folder_children else: - folder_children = MSVSNew.MSVSFolder(os.path.join(base_path, folder), - name='(' + folder + ')', - entries=folder_children) + folder_children = MSVSNew.MSVSFolderEntry(os.path.join(base_path, folder), + name='(' + folder + ')', + entries=folder_children) children.append(folder_children) else: children.append(contents) @@ -1778,8 +1474,8 @@ def _CollapseSingles(parent, node): # such projects up one level. if (type(node) == dict and len(node) == 1 and - node.keys()[0] == parent + '.vcproj'): - return node[node.keys()[0]] + next(iter(node)) == parent + '.vcproj'): + return node[next(iter(node))] if type(node) != dict: return node for child in node: @@ -1791,15 +1487,15 @@ def _GatherSolutionFolders(sln_projects, project_objects, flat): root = {} # Convert into a tree of dicts on path. for p in sln_projects: - gyp_file, target = gyp.common.ParseQualifiedTarget(p)[0:2] + gyp_file, target = common.ParseQualifiedTarget(p)[0:2] gyp_dir = os.path.dirname(gyp_file) path_dict = _GetPathDict(root, gyp_dir) path_dict[target + '.vcproj'] = project_objects[p] # Walk down from the top until we hit a folder that has more than one entry. # In practice, this strips the top-level "src/" dir from the hierarchy in # the solution. - while len(root) == 1 and type(root[root.keys()[0]]) == dict: - root = root[root.keys()[0]] + while len(root) == 1 and type(root[next(iter(root))]) == dict: + root = root[next(iter(root))] # Collapse singles. root = _CollapseSingles('', root) # Merge buckets until everything is a root entry. @@ -1813,14 +1509,13 @@ def _GetPathOfProject(qualified_target, spec, options, msvs_version): proj_filename = (spec['target_name'] + options.suffix + msvs_version.ProjectExtension()) - build_file = gyp.common.BuildFile(qualified_target) + build_file = common.BuildFile(qualified_target) proj_path = os.path.join(os.path.dirname(build_file), proj_filename) fix_prefix = None if options.generator_output: project_dir_path = os.path.dirname(os.path.abspath(proj_path)) proj_path = os.path.join(options.generator_output, proj_path) - fix_prefix = gyp.common.RelativePath(project_dir_path, - os.path.dirname(proj_path)) + fix_prefix = common.RelativePath(project_dir_path, os.path.dirname(proj_path)) return proj_path, fix_prefix @@ -1828,11 +1523,10 @@ def _GetPlatformOverridesOfProject(spec): # Prepare a dict indicating which project configurations are used for which # solution configurations for this target. config_platform_overrides = {} - for config_name, c in spec['configurations'].iteritems(): + for config_name, c in spec['configurations'].items(): config_fullname = _ConfigFullName(config_name, c) platform = c.get('msvs_target_platform', _ConfigPlatform(c)) - fixed_config_fullname = '%s|%s' % ( - _ConfigBaseName(config_name, _ConfigPlatform(c)), platform) + fixed_config_fullname = '%s|%s' % (_ConfigBaseName(config_name, _ConfigPlatform(c)), platform) config_platform_overrides[config_fullname] = fixed_config_fullname return config_platform_overrides @@ -1854,16 +1548,13 @@ def _CreateProjectObjects(target_list, target_dicts, options, msvs_version): for qualified_target in target_list: spec = target_dicts[qualified_target] if spec['toolset'] != 'target': - raise GypError( - 'Multiple toolsets not supported in msvs build (target %s)' % - qualified_target) - proj_path, fixpath_prefix = _GetPathOfProject(qualified_target, spec, - options, msvs_version) - guid = _GetGuidOfProject(proj_path, spec) + raise GypError('Multiple toolsets not supported in msvs build (target %s)' % qualified_target) + proj_path, fixpath_prefix = _GetPathOfProject(qualified_target, spec, options, msvs_version) + guid = _TryGetGuidOfProject(spec) overrides = _GetPlatformOverridesOfProject(spec) - build_file = gyp.common.BuildFile(qualified_target) + build_file = common.BuildFile(qualified_target) # Create object for this project. - obj = MSVSNew.MSVSProject( + obj = MSVSNew.MSVSProjectEntry( proj_path, name=spec['target_name'], guid=guid, @@ -1872,9 +1563,8 @@ def _CreateProjectObjects(target_list, target_dicts, options, msvs_version): config_platform_overrides=overrides, fixpath_prefix=fixpath_prefix) # Set project toolset if any (MS build only) - if msvs_version.UsesVcxproj(): - obj.set_msbuild_toolset( - _GetMsbuildToolsetOfProject(proj_path, spec, msvs_version)) + if msvs_version.uses_vcxproj: + obj.set_msbuild_toolset(_GetMsbuildToolsetOfProject(spec, msvs_version)) projects[qualified_target] = obj # Set all the dependencies, but not if we are using an external builder like # ninja @@ -1908,13 +1598,15 @@ def _InitNinjaFlavor(params, target_list, target_dicts): spec['msvs_external_builder'] = 'ninja' if not spec.get('msvs_external_builder_out_dir'): - gyp_file, _, _ = gyp.common.ParseQualifiedTarget(qualified_target) + gyp_file, _, _ = common.ParseQualifiedTarget(qualified_target) gyp_dir = os.path.dirname(gyp_file) configuration = '$(Configuration)' if params.get('target_arch') == 'x64': configuration += '_x64' + if params.get('target_arch') == 'arm64': + configuration += '_arm64' spec['msvs_external_builder_out_dir'] = os.path.join( - gyp.common.RelativePath(params['options'].toplevel_dir, gyp_dir), + common.RelativePath(params['options'].toplevel_dir, gyp_dir), ninja_generator.ComputeOutputDir(params), configuration) if not spec.get('msvs_external_builder_build_cmd'): @@ -1940,13 +1632,13 @@ def CalculateVariables(default_variables, params): generator_flags = params.get('generator_flags', {}) # Select project file format version (if unset, default to auto detecting). - msvs_version = MSVSVersion.SelectVisualStudioVersion( - generator_flags.get('msvs_version', 'auto')) + msvs_version = generator_flags.get('msvs_version', 'auto') + msvs_version = MSVSVersion.SelectVisualStudioVersion(msvs_version) # Stash msvs_version for later (so we don't have to probe the system twice). params['msvs_version'] = msvs_version # Set a variable so conditions can be based on msvs_version. - default_variables['MSVS_VERSION'] = msvs_version.ShortName() + default_variables['MSVS_VERSION'] = msvs_version.short_name # To determine processor word size on Windows, in addition to checking # PROCESSOR_ARCHITECTURE (which reflects the word size of the current @@ -1958,7 +1650,7 @@ def CalculateVariables(default_variables, params): else: default_variables['MSVS_OS_BITS'] = 32 - if gyp.common.GetFlavor(params) == 'ninja': + if common.GetFlavor(params) == 'ninja': default_variables['SHARED_INTERMEDIATE_DIR'] = '$(OutDir)gen' @@ -1967,18 +1659,20 @@ def PerformBuild(data, configurations, params): msvs_version = params['msvs_version'] devenv = os.path.join(msvs_version.path, 'Common7', 'IDE', 'devenv.com') - for build_file, build_file_dict in data.iteritems(): + sln_path = '' + for build_file, build_file_dict in data.items(): (build_file_root, build_file_ext) = os.path.splitext(build_file) if build_file_ext != '.gyp': continue sln_path = build_file_root + options.suffix + '.sln' if options.generator_output: sln_path = os.path.join(options.generator_output, sln_path) + assert sln_path for config in configurations: arguments = [devenv, sln_path, '/Build', config] - print 'Building [%s]: %s' % (config, arguments) - rtn = subprocess.check_call(arguments) + print('Building [%s]: %s' % (config, arguments)) + subprocess.check_call(arguments) def CalculateGeneratorInputInfo(params): @@ -2002,6 +1696,7 @@ def GenerateOutput(target_list, target_dicts, data, params): target_list: List of target pairs: 'base/base.gyp:base'. target_dicts: Dict of target properties keyed on target pair. data: Dictionary containing per .gyp data. + params: """ global fixpath_prefix @@ -2014,12 +1709,11 @@ def GenerateOutput(target_list, target_dicts, data, params): generator_flags = params.get('generator_flags', {}) # Optionally shard targets marked with 'msvs_shard': SHARD_COUNT. - (target_list, target_dicts) = MSVSUtil.ShardTargets(target_list, target_dicts) + (target_list, target_dicts) = MSVS.ShardTargets(target_list, target_dicts) # Optionally use the large PDB workaround for targets marked with # 'msvs_large_pdb': 1. - (target_list, target_dicts) = MSVSUtil.InsertLargePdbShims( - target_list, target_dicts, generator_default_variables) + (target_list, target_dicts) = MSVS.InsertLargePdbShims(target_list, target_dicts, generator_default_variables) # Optionally configure each spec to use ninja as the external builder. if params.get('flavor') == 'ninja': @@ -2029,20 +1723,19 @@ def GenerateOutput(target_list, target_dicts, data, params): configs = set() for qualified_target in target_list: spec = target_dicts[qualified_target] - for config_name, config in spec['configurations'].iteritems(): + for config_name, config in spec['configurations'].items(): configs.add(_ConfigFullName(config_name, config)) configs = list(configs) # Figure out all the projects that will be generated and their guids - project_objects = _CreateProjectObjects(target_list, target_dicts, options, - msvs_version) + project_objects = _CreateProjectObjects(target_list, target_dicts, options, msvs_version) # Generate each project. missing_sources = [] for project in project_objects.values(): fixpath_prefix = project.fixpath_prefix - missing_sources.extend(_GenerateProject(project, options, msvs_version, - generator_flags)) + generated_project = _GenerateProject(project, options, msvs_version, generator_flags) + missing_sources.extend(generated_project) fixpath_prefix = None for build_file in data: @@ -2053,31 +1746,23 @@ def GenerateOutput(target_list, target_dicts, data, params): if options.generator_output: sln_path = os.path.join(options.generator_output, sln_path) # Get projects in the solution, and their dependents. - sln_projects = gyp.common.BuildFileTargets(target_list, build_file) - sln_projects += gyp.common.DeepDependencyTargets(target_dicts, sln_projects) + sln_projects = common.BuildFileTargets(target_list, build_file) + sln_projects += common.DeepDependencyTargets(target_dicts, sln_projects) # Create folder hierarchy. - root_entries = _GatherSolutionFolders( - sln_projects, project_objects, flat=msvs_version.FlatSolution()) + root_entries = _GatherSolutionFolders(sln_projects, project_objects, flat=msvs_version.flat_sln) # Create solution. - sln = MSVSNew.MSVSSolution(sln_path, - entries=root_entries, - variants=configs, - websiteProperties=False, - version=msvs_version) + sln = MSVSNew.MSVSSolution(sln_path, entries=root_entries, variants=configs, websiteProperties=False, version=msvs_version) sln.Write() if missing_sources: - error_message = "Missing input files:\n" + \ - '\n'.join(set(missing_sources)) + error_message = "Missing input files:\n" + '\n'.join(set(missing_sources)) if generator_flags.get('msvs_error_on_missing_sources', False): raise GypError(error_message) else: - print >> sys.stdout, "Warning: " + error_message + print("Warning: " + error_message) -def _GenerateMSBuildFiltersFile(filters_path, source_files, - rule_dependencies, extension_to_rule_name, - platforms): +def _GenerateMSBuildFiltersFile(filters_path, source_files, rule_dependencies, extension_to_rule_name, platforms): """Generate the filters file. This file is used by Visual Studio to organize the presentation of source @@ -2094,13 +1779,12 @@ def _GenerateMSBuildFiltersFile(filters_path, source_files, extension_to_rule_name, platforms, filter_group, source_group) if filter_group: - content = ['Project', - {'ToolsVersion': '4.0', - 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003' - }, - ['ItemGroup'] + filter_group, - ['ItemGroup'] + source_group - ] + content = [ + 'Project', + {'ToolsVersion': '4.0', 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}, + ['ItemGroup'] + filter_group, + ['ItemGroup'] + source_group + ] easy_xml.WriteXmlIfChanged(content, filters_path, pretty=True, win32=True) elif os.path.exists(filters_path): # We don't need this filter anymore. Delete the old filter file. @@ -2121,25 +1805,21 @@ def _AppendFiltersForMSBuild(parent_filter_name, sources, rule_dependencies, source_group: The list to which source entries will be appeneded. """ for source in sources: - if isinstance(source, MSVSProject.Filter): + if isinstance(source, MSVS.Filter): # We have a sub-filter. Create the name of that sub-filter. if not parent_filter_name: filter_name = source.name else: filter_name = '%s\\%s' % (parent_filter_name, source.name) # Add the filter to the group. - filter_group.append( - ['Filter', {'Include': filter_name}, - ['UniqueIdentifier', MSVSNew.MakeGuid(source.name)]]) + filter_group.append(['Filter', {'Include': filter_name}, ['UniqueIdentifier', MSVSNew.MSVSProjectEntry.MakeGuid(source.name)]]) # Recurse and add its dependents. _AppendFiltersForMSBuild(filter_name, source.contents, rule_dependencies, extension_to_rule_name, platforms, filter_group, source_group) else: # It's a source. Create a source entry. - _, element = _MapFileToMsBuildSourceType(source, rule_dependencies, - extension_to_rule_name, - platforms) + _, element = _MapFileToMsBuildSourceType(source, rule_dependencies, extension_to_rule_name, platforms) source_entry = [element, {'Include': source}] # Specify the filter it is part of, if any. if parent_filter_name: @@ -2147,8 +1827,7 @@ def _AppendFiltersForMSBuild(parent_filter_name, sources, rule_dependencies, source_group.append(source_entry) -def _MapFileToMsBuildSourceType(source, rule_dependencies, - extension_to_rule_name, platforms): +def _MapFileToMsBuildSourceType(source, rule_dependencies, extension_to_rule_name, platforms): """Returns the group and element type of the source file. Arguments: @@ -2159,7 +1838,6 @@ def _MapFileToMsBuildSourceType(source, rule_dependencies, A pair of (group this file should be part of, the label of element) """ _, ext = os.path.splitext(source) - ext = ext.lower() if ext in extension_to_rule_name: group = 'rule' element = extension_to_rule_name[ext] @@ -2172,7 +1850,7 @@ def _MapFileToMsBuildSourceType(source, rule_dependencies, elif ext == '.rc': group = 'resource' element = 'ResourceCompile' - elif ext in ['.s', '.asm']: + elif ext in ('.asm', '.s', '.S'): group = 'masm' element = 'MASM' for platform in platforms: @@ -2187,7 +1865,7 @@ def _MapFileToMsBuildSourceType(source, rule_dependencies, else: group = 'none' element = 'None' - return (group, element) + return group, element def _GenerateRulesForMSBuild(output_dir, options, spec, @@ -2666,104 +2344,91 @@ def _GenerateMSBuildRuleXmlFile(xml_path, msbuild_rules): def _GetConfigurationAndPlatform(name, settings): configuration = name.rsplit('_', 1)[0] platform = settings.get('msvs_configuration_platform', 'Win32') - return (configuration, platform) + return configuration, platform def _GetConfigurationCondition(name, settings): - return (r"'$(Configuration)|$(Platform)'=='%s|%s'" % - _GetConfigurationAndPlatform(name, settings)) + return r"'$(Configuration)|$(Platform)'=='%s|%s'" % _GetConfigurationAndPlatform(name, settings) def _GetMSBuildProjectConfigurations(configurations): group = ['ItemGroup', {'Label': 'ProjectConfigurations'}] - for (name, settings) in sorted(configurations.iteritems()): + for (name, settings) in sorted(configurations.items()): configuration, platform = _GetConfigurationAndPlatform(name, settings) designation = '%s|%s' % (configuration, platform) - group.append( - ['ProjectConfiguration', {'Include': designation}, - ['Configuration', configuration], - ['Platform', platform]]) + group.append([ + 'ProjectConfiguration', + {'Include': designation}, + ['Configuration', configuration], + ['Platform', platform] + ]) return [group] def _GetMSBuildGlobalProperties(spec, version, guid, gyp_file_name): namespace = os.path.splitext(gyp_file_name)[0] properties = [ - ['PropertyGroup', {'Label': 'Globals'}, - ['ProjectGuid', guid], - ['Keyword', 'Win32Proj'], - ['RootNamespace', namespace], - ['IgnoreWarnCompileDuplicatedFilename', 'true'], - ] - ] + 'PropertyGroup', + {'Label': 'Globals'}, + ['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']) + properties.append(['PreferredToolArchitecture', 'x64']) if spec.get('msvs_target_platform_version'): target_platform_version = spec.get('msvs_target_platform_version') - properties[0].append(['WindowsTargetPlatformVersion', - target_platform_version]) + properties.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]) + properties.append(['WindowsTargetPlatformMinVersion', target_platform_minversion]) else: - properties[0].append(['WindowsTargetPlatformMinVersion', - target_platform_version]) + properties.append(['WindowsTargetPlatformMinVersion', target_platform_version]) if spec.get('msvs_enable_winrt'): - properties[0].append(['DefaultLanguage', 'en-US']) - properties[0].append(['AppContainerApplication', 'true']) + properties.append(['DefaultLanguage', 'en-US']) + properties.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]) + properties.append(['ApplicationTypeRevision', app_type_revision]) else: - properties[0].append(['ApplicationTypeRevision', '8.1']) + properties.append(['ApplicationTypeRevision', '8.1']) if spec.get('msvs_enable_winphone'): - properties[0].append(['ApplicationType', 'Windows Phone']) + properties.append(['ApplicationType', 'Windows Phone']) else: - properties[0].append(['ApplicationType', 'Windows Store']) - - platform_name = None - msvs_windows_sdk_version = None - for configuration in spec['configurations'].itervalues(): - platform_name = platform_name or _ConfigPlatform(configuration) - msvs_windows_sdk_version = (msvs_windows_sdk_version or - _ConfigWindowsTargetPlatformVersion(configuration, version)) - if platform_name and msvs_windows_sdk_version: - break + properties.append(['ApplicationType', 'Windows Store']) + + configuration = spec['configurations'][spec['default_configuration']] + platform_name = _ConfigPlatform(configuration) + possible_sdk_versions = configuration.get('msvs_windows_sdk_version', version.compatible_sdks) + msvs_windows_sdk_version = MSVSVersion.WindowsTargetPlatformVersion(possible_sdk_versions) if msvs_windows_sdk_version: - properties[0].append(['WindowsTargetPlatformVersion', - str(msvs_windows_sdk_version)]) - elif version.compatible_sdks: - raise GypError('%s requires any SDK of %s version, but none were found' % - (version.description, version.compatible_sdks)) + properties.append(['WindowsTargetPlatformVersion', str(msvs_windows_sdk_version)]) if platform_name == 'ARM': - properties[0].append(['WindowsSDKDesktopARMSupport', 'true']) + properties.append(['WindowsSDKDesktopARMSupport', 'true']) - return properties + return [properties] def _GetMSBuildConfigurationDetails(spec, build_file): properties = {} - for name, settings in spec['configurations'].iteritems(): + for name, settings in spec['configurations'].items(): msbuild_attributes = _GetMSBuildAttributes(spec, settings, build_file) condition = _GetConfigurationCondition(name, settings) character_set = msbuild_attributes.get('CharacterSet') config_type = msbuild_attributes.get('ConfigurationType') - _AddConditionalProperty(properties, condition, 'ConfigurationType', - config_type) + _AddConditionalProperty(properties, condition, 'ConfigurationType', config_type) if config_type == 'Driver': _AddConditionalProperty(properties, condition, 'DriverType', 'WDM') - _AddConditionalProperty(properties, condition, 'TargetVersion', - _ConfigTargetVersion(settings)) + _AddConditionalProperty(properties, condition, 'TargetVersion', _ConfigTargetVersion(settings)) if character_set: - if 'msvs_enable_winrt' not in spec : - _AddConditionalProperty(properties, condition, 'CharacterSet', - character_set) + if 'msvs_enable_winrt' not in spec: + _AddConditionalProperty(properties, condition, 'CharacterSet', character_set) return _GetMSBuildPropertyGroup(spec, 'Configuration', properties) @@ -2783,9 +2448,9 @@ def _GetMSBuildPropertySheets(configurations): user_props = r'$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props' additional_props = {} props_specified = False - for name, settings in sorted(configurations.iteritems()): + for name, settings in sorted(configurations.items()): configuration = _GetConfigurationCondition(name, settings) - if settings.has_key('msbuild_props'): + if 'msbuild_props' in settings: additional_props[configuration] = _FixPaths(settings['msbuild_props']) props_specified = True else: @@ -2805,7 +2470,7 @@ def _GetMSBuildPropertySheets(configurations): ] else: sheets = [] - for condition, props in additional_props.iteritems(): + for condition, props in additional_props.items(): import_group = [ 'ImportGroup', {'Label': 'PropertySheets', @@ -2825,7 +2490,7 @@ def _GetMSBuildPropertySheets(configurations): def _ConvertMSVSBuildAttributes(spec, config, build_file): config_type = _GetMSVSConfigurationType(spec, build_file) - msvs_attributes = _GetMSVSAttributes(spec, config, config_type) + msvs_attributes = _GetMSVSAttributes(config, config_type) msbuild_attributes = {} for a in msvs_attributes: if a in ['IntermediateDirectory', 'OutputDirectory']: @@ -2838,7 +2503,7 @@ def _ConvertMSVSBuildAttributes(spec, config, build_file): elif a == 'ConfigurationType': msbuild_attributes[a] = _ConvertMSVSConfigurationType(msvs_attributes[a]) else: - print 'Warning: Do not know how to convert MSVS attribute ' + a + print('Warning: Do not know how to convert MSVS attribute ' + a) return msbuild_attributes @@ -2934,34 +2599,28 @@ def _GetMSBuildConfigurationGlobalProperties(spec, configurations, build_file): new_paths = '$(ExecutablePath);' + ';'.join(new_paths) properties = {} - for (name, configuration) in sorted(configurations.iteritems()): + for (name, configuration) in sorted(configurations.items()): condition = _GetConfigurationCondition(name, configuration) attributes = _GetMSBuildAttributes(spec, configuration, build_file) msbuild_settings = configuration['finalized_msbuild_settings'] - _AddConditionalProperty(properties, condition, 'IntDir', - attributes['IntermediateDirectory']) - _AddConditionalProperty(properties, condition, 'OutDir', - attributes['OutputDirectory']) - _AddConditionalProperty(properties, condition, 'TargetName', - attributes['TargetName']) + _AddConditionalProperty(properties, condition, 'IntDir', attributes['IntermediateDirectory']) + _AddConditionalProperty(properties, condition, 'OutDir', attributes['OutputDirectory']) + _AddConditionalProperty(properties, condition, 'TargetName', attributes['TargetName']) if 'TargetExt' in attributes: - _AddConditionalProperty(properties, condition, 'TargetExt', - attributes['TargetExt']) + _AddConditionalProperty(properties, condition, 'TargetExt', attributes['TargetExt']) if attributes.get('TargetPath'): - _AddConditionalProperty(properties, condition, 'TargetPath', - attributes['TargetPath']) + _AddConditionalProperty(properties, condition, 'TargetPath', attributes['TargetPath']) if attributes.get('TargetExt'): - _AddConditionalProperty(properties, condition, 'TargetExt', - attributes['TargetExt']) + _AddConditionalProperty(properties, condition, 'TargetExt', attributes['TargetExt']) if new_paths: - _AddConditionalProperty(properties, condition, 'ExecutablePath', - new_paths) + _AddConditionalProperty(properties, condition, 'ExecutablePath', new_paths) tool_settings = msbuild_settings.get('', {}) - for name, value in sorted(tool_settings.iteritems()): - formatted_value = _GetValueFormattedForMSBuild('', name, value) - _AddConditionalProperty(properties, condition, name, formatted_value) + for name2, value in sorted(tool_settings.items()): + formatted_value = _GetValueFormattedForMSBuild('', name2, value) + _AddConditionalProperty(properties, condition, name2, formatted_value) + return _GetMSBuildPropertyGroup(spec, None, properties) @@ -2999,16 +2658,12 @@ def _GetMSBuildPropertyGroup(spec, label, properties): property. The value is itself a dictionary; its key is the value and the value a list of condition for which this value is true. """ - group = ['PropertyGroup'] - if label: - group.append({'Label': label}) - num_configurations = len(spec['configurations']) def GetEdges(node): # Use a definition of edges such that user_of_variable -> used_varible. # This happens to be easier in this case, since a variable's # definition contains all variables it references in a single string. edges = set() - for value in sorted(properties[node].keys()): + for val in sorted(properties[node].keys()): # Add to edges all $(...) references to variables. # # Variable references that refer to names not in properties are excluded @@ -3017,18 +2672,21 @@ def GetEdges(node): # # Self references are ignored. Self reference is used in a few places to # append to the default value. I.e. PATH=$(PATH);other_path - edges.update(set([v for v in MSVS_VARIABLE_REFERENCE.findall(value) - if v in properties and v != node])) + edges.update(set([v for v in MSVS_VARIABLE_REFERENCE.findall(val) if v in properties and v != node])) return edges - properties_ordered = gyp.common.TopologicallySorted( - properties.keys(), GetEdges) + + group = ['PropertyGroup'] + if label: + group.append({'Label': label}) + num_configurations = len(spec['configurations']) + properties_ordered = common.TopologicallySorted(properties.keys(), GetEdges) # Walk properties in the reverse of a topological sort on # user_of_variable -> used_variable as this ensures variables are # defined before they are used. # NOTE: reverse(topsort(DAG)) = topsort(reverse_edges(DAG)) for name in reversed(properties_ordered): values = properties[name] - for value, conditions in sorted(values.iteritems()): + for value, conditions in sorted(values.items()): if len(conditions) == num_configurations: # If the value is the same all configurations, # just add one unconditional entry. @@ -3039,24 +2697,21 @@ def GetEdges(node): return [group] -def _GetMSBuildToolSettingsSections(spec, configurations): +def _GetMSBuildToolSettingsSections(configurations): groups = [] - for (name, configuration) in sorted(configurations.iteritems()): + for (name, configuration) in sorted(configurations.items()): msbuild_settings = configuration['finalized_msbuild_settings'] - group = ['ItemDefinitionGroup', - {'Condition': _GetConfigurationCondition(name, configuration)} - ] - for tool_name, tool_settings in sorted(msbuild_settings.iteritems()): + group = ['ItemDefinitionGroup', {'Condition': _GetConfigurationCondition(name, configuration)}] + for tool_name, tool_settings in sorted(msbuild_settings.items()): # Skip the tool named '' which is a holder of global settings handled # by _GetMSBuildConfigurationGlobalProperties. - if tool_name: - if tool_settings: - tool = [tool_name] - for name, value in sorted(tool_settings.iteritems()): - formatted_value = _GetValueFormattedForMSBuild(tool_name, name, - value) - tool.append([name, formatted_value]) - group.append(tool) + if not tool_name or not tool_settings: + continue + tool = [tool_name] + for name2, value in sorted(tool_settings.items()): + formatted_value = _GetValueFormattedForMSBuild(tool_name, name2, value) + tool.append([name2, formatted_value]) + group.append(tool) groups.append(group) return groups @@ -3070,8 +2725,7 @@ def _FinalizeMSBuildSettings(spec, configuration): converted = True msvs_settings = configuration.get('msvs_settings', {}) msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(msvs_settings) - include_dirs, midl_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) @@ -3085,8 +2739,8 @@ def _FinalizeMSBuildSettings(spec, configuration): for ignored_setting in ignored_settings: value = configuration.get(ignored_setting) if value: - print ('Warning: The automatic conversion to MSBuild does not handle ' - '%s. Ignoring setting of %s' % (ignored_setting, str(value))) + print('Warning: The automatic conversion to MSBuild does not handle ' + '%s. Ignoring setting of %s' % (ignored_setting, str(value))) defines = [_EscapeCppDefineForMSBuild(d) for d in defines] disabled_warnings = _GetDisabledWarnings(configuration) @@ -3197,7 +2851,7 @@ def _VerifySourcesExist(sources, root_dir): """ missing_sources = [] for source in sources: - if isinstance(source, MSVSProject.Filter): + if isinstance(source, MSVS.Filter): missing_sources.extend(_VerifySourcesExist(source.contents, root_dir)) else: if '$' not in source: @@ -3234,7 +2888,7 @@ def _AddSources2(spec, sources, exclusions, grouped_sources, list_excluded): extensions_excluded_from_precompile = [] for source in sources: - if isinstance(source, MSVSProject.Filter): + if isinstance(source, MSVS.Filter): _AddSources2(spec, source.contents, exclusions, grouped_sources, rule_dependencies, extension_to_rule_name, sources_handled_by_action, @@ -3252,7 +2906,7 @@ def _AddSources2(spec, sources, exclusions, grouped_sources, {'Condition': condition}, 'true']) # Add precompile if needed - for config_name, configuration in spec['configurations'].iteritems(): + for config_name, configuration in spec['configurations'].items(): precompiled_source = configuration.get('msvs_precompiled_source', '') if precompiled_source != '': precompiled_source = _FixPath(precompiled_source) @@ -3293,13 +2947,13 @@ def _GetMSBuildProjectReferences(project): for dependency in project.dependencies: guid = dependency.guid project_dir = os.path.split(project.path)[0] - relative_path = gyp.common.RelativePath(dependency.path, project_dir) + relative_path = common.RelativePath(dependency.path, project_dir) project_ref = ['ProjectReference', {'Include': relative_path}, ['Project', guid], ['ReferenceOutputAssembly', 'false'] ] - for config in dependency.spec.get('configurations', {}).itervalues(): + for config in dependency.spec.get('configurations', {}).values(): if config.get('msvs_use_library_dependency_inputs', 0): project_ref.append(['UseLibraryDependencyInputs', 'true']) break @@ -3316,16 +2970,14 @@ def _GenerateMSBuildProject(project, options, version, generator_flags): spec = project.spec configurations = spec['configurations'] project_dir, project_file_name = os.path.split(project.path) - gyp.common.EnsureDirExists(project.path) + 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) - + # gyp_path = _NormalizedSource(project.build_file) + # relative_path_of_gyp_file = common.RelativePath(gyp_path, project_dir) gyp_file = os.path.split(project.build_file)[1] - sources, excluded_sources = _PrepareListOfSources(spec, generator_flags, - gyp_file) + sources, excluded_sources = _PrepareListOfSources(spec, generator_flags, gyp_file) # Add rules. - actions_to_add = {} + actions_to_add = OrderedDict() props_files_of_rules = set() targets_files_of_rules = set() rule_dependencies = set() @@ -3343,11 +2995,7 @@ def _GenerateMSBuildProject(project, options, version, generator_flags): rules = spec.get('rules', []) _AdjustSourcesForRules(rules, sources, excluded_sources, True) - sources, excluded_sources, excluded_idl = ( - _AdjustSourcesAndConvertToFilterHierarchy(spec, options, - project_dir, sources, - excluded_sources, - list_excluded, version)) + sources, excluded_sources, excluded_idl = _AdjustSourcesAndConvertToFilterHierarchy(spec, sources, excluded_sources, list_excluded, version) # Don't add actions if we are using an external builder like ninja. if not spec.get('msvs_external_builder'): @@ -3356,71 +3004,53 @@ def _GenerateMSBuildProject(project, options, version, generator_flags): # NOTE: this stanza must appear after all actions have been decided. # Don't excluded sources with actions attached, or they won't run. - excluded_sources = _FilterActionsFromExcluded( - excluded_sources, actions_to_add) + excluded_sources = _FilterActionsFromExcluded(excluded_sources, actions_to_add) exclusions = _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl) - actions_spec, sources_handled_by_action = _GenerateActionsForMSBuild( - spec, actions_to_add) + actions_spec, sources_handled_by_action = _GenerateActionsForMSBuild(actions_to_add) - _GenerateMSBuildFiltersFile(project.path + '.filters', sources, - rule_dependencies, - extension_to_rule_name, _GetUniquePlatforms(spec)) + _GenerateMSBuildFiltersFile(project.path + '.filters', sources, rule_dependencies,extension_to_rule_name, _GetUniquePlatforms(spec)) missing_sources = _VerifySourcesExist(sources, project_dir) - for configuration in configurations.itervalues(): + for configuration in configurations.values(): _FinalizeMSBuildSettings(spec, configuration) # Add attributes to root element - import_default_section = [ - ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.Default.props'}]] - import_cpp_props_section = [ - ['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'}]] - import_marmasm_props_section = [ - ['Import', - {'Project': r'$(VCTargetsPath)\BuildCustomizations\marmasm.props'}]] - import_marmasm_targets_section = [ - ['Import', - {'Project': r'$(VCTargetsPath)\BuildCustomizations\marmasm.targets'}]] + import_default_section = [['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.Default.props'}]] + import_cpp_props_section = [['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'}]] + import_marmasm_props_section = [['Import', {'Project': r'$(VCTargetsPath)\BuildCustomizations\marmasm.props'}]] + import_marmasm_targets_section = [['Import', {'Project': r'$(VCTargetsPath)\BuildCustomizations\marmasm.targets'}]] macro_section = [['PropertyGroup', {'Label': 'UserMacros'}]] content = [ - 'Project', - {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003', - 'ToolsVersion': version.ProjectVersion(), - 'DefaultTargets': 'Build' - }] + 'Project', { + 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003', + 'ToolsVersion': version.project_version, + 'DefaultTargets': 'Build', + }, + ] content += _GetMSBuildProjectConfigurations(configurations) - content += _GetMSBuildGlobalProperties(spec, version, project.guid, - project_file_name) + content += _GetMSBuildGlobalProperties(spec, version, project.guid, project_file_name) content += import_default_section content += _GetMSBuildConfigurationDetails(spec, project.build_file) if spec.get('msvs_enable_winphone'): - content += _GetMSBuildLocalProperties('v120_wp81') + content += _GetMSBuildLocalProperties('v120_wp81') else: - content += _GetMSBuildLocalProperties(project.msbuild_toolset) + content += _GetMSBuildLocalProperties(project.msbuild_toolset) content += import_cpp_props_section content += import_masm_props_section content += import_marmasm_props_section content += _GetMSBuildExtensions(props_files_of_rules) content += _GetMSBuildPropertySheets(configurations) content += macro_section - content += _GetMSBuildConfigurationGlobalProperties(spec, configurations, - project.build_file) - content += _GetMSBuildToolSettingsSections(spec, configurations) - content += _GetMSBuildSources( - spec, sources, exclusions, rule_dependencies, extension_to_rule_name, - actions_spec, sources_handled_by_action, list_excluded) + content += _GetMSBuildConfigurationGlobalProperties(spec, configurations, project.build_file) + content += _GetMSBuildToolSettingsSections(configurations) + content += _GetMSBuildSources(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 @@ -3439,7 +3069,8 @@ def _GenerateMSBuildProject(project, options, version, generator_flags): def _GetMSBuildExternalBuilderTargets(spec): - """Return a list of MSBuild targets for external builders. + """ + Return a list of MSBuild targets for external builders. The "Build" and "Clean" targets are always generated. If the spec contains 'msvs_external_builder_clcompile_cmd', then the "ClCompile" target will also @@ -3450,27 +3081,31 @@ def _GetMSBuildExternalBuilderTargets(spec): Returns: List of MSBuild 'Target' specs. """ - build_cmd = _BuildCommandLineForRuleRaw( - spec, spec['msvs_external_builder_build_cmd'], - False, False, False, False) - build_target = ['Target', {'Name': 'Build'}] - build_target.append(['Exec', {'Command': build_cmd}]) - - clean_cmd = _BuildCommandLineForRuleRaw( - spec, spec['msvs_external_builder_clean_cmd'], - False, False, False, False) - clean_target = ['Target', {'Name': 'Clean'}] - clean_target.append(['Exec', {'Command': clean_cmd}]) - - 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) + build_cmd = _BuildCommandLineForRuleRaw(spec, spec['msvs_external_builder_build_cmd'], False, False, False, False) + clean_cmd = _BuildCommandLineForRuleRaw(spec, spec['msvs_external_builder_clean_cmd'], False, False, False, False) + targets = [ + [ + 'Target', + {'Name': 'Build'}, + ['Exec', {'Command': build_cmd}] + ], + [ + 'Target', + {'Name': 'Clean'}, + ['Exec', {'Command': clean_cmd}] + ] + ] + + compile_cmd_txt = spec.get('msvs_external_builder_clcompile_cmd') + if compile_cmd_txt: + compile_cmd = _BuildCommandLineForRuleRaw(spec, compile_cmd_txt, False, False, False, False) + targets.append( + [ + 'Target', + {'Name': 'ClCompile'}, + ['Exec', {'Command': compile_cmd}], + ] + ) return targets @@ -3489,11 +3124,11 @@ def _GetMSBuildExtensionTargets(targets_files_of_rules): return [targets_node] -def _GenerateActionsForMSBuild(spec, actions_to_add): - """Add actions accumulated into an actions_to_add, merging as needed. +def _GenerateActionsForMSBuild(actions_to_add): + """ + Add actions accumulated into an actions_to_add, merging as needed. Arguments: - spec: the target project dict actions_to_add: dictionary keyed on input name, which maps to a list of dicts describing the actions attached to that input file. @@ -3502,7 +3137,7 @@ def _GenerateActionsForMSBuild(spec, actions_to_add): """ sources_handled_by_action = OrderedSet() actions_spec = [] - for primary_input, actions in actions_to_add.iteritems(): + for primary_input, actions in actions_to_add.items(): inputs = OrderedSet() outputs = OrderedSet() descriptions = [] @@ -3526,27 +3161,17 @@ def _GenerateActionsForMSBuild(spec, actions_to_add): # 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\n'.join([c + '\r\nif %errorlevel% neq 0 exit /b %errorlevel%' - for c in commands]) - _AddMSBuildAction(spec, - primary_input, - inputs, - outputs, - command, - description, - sources_handled_by_action, - actions_spec) + command = '\r\n'.join([c + '\r\nif %errorlevel% neq 0 exit /b %errorlevel%' for c in commands]) + _AddMSBuildAction(primary_input, inputs, outputs, command, description, sources_handled_by_action, actions_spec) return actions_spec, sources_handled_by_action -def _AddMSBuildAction(spec, primary_input, inputs, outputs, cmd, description, - sources_handled_by_action, actions_spec): +def _AddMSBuildAction(primary_input, inputs, outputs, cmd, description, sources_handled_by_action, actions_spec): command = MSVSSettings.ConvertVCMacrosToMSBuild(cmd) primary_input = _FixPath(primary_input) inputs_array = _FixPaths(inputs) outputs_array = _FixPaths(outputs) - additional_inputs = ';'.join([i for i in inputs_array - if i != primary_input]) + additional_inputs = ';'.join([i for i in inputs_array if i != primary_input]) outputs = ';'.join(outputs_array) sources_handled_by_action.add(primary_input) action_spec = ['CustomBuild', {'Include': primary_input}] diff --git a/tools/gyp/gyp/generator/ninja.py b/tools/gyp/gyp/generator/ninja.py new file mode 100644 index 00000000000000..255ede256e62e2 --- /dev/null +++ b/tools/gyp/gyp/generator/ninja.py @@ -0,0 +1,806 @@ +# 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 __future__ import print_function + +import codecs +import hashlib +import os.path +import re +import subprocess +import sys +from collections import OrderedDict + +import gyp +import gyp.common +import gyp.msvs_emulation +import gyp.xcode_emulation +import gyp.MSVS as MSVS +from gyp.common import GetEnvironFallback +from gyp.lib import ninja_syntax + +try: + # noinspection PyCompatibility + from cStringIO import StringIO +except ImportError: + from io import StringIO + + +generator_default_variables = { + 'EXECUTABLE_PREFIX': '', + 'EXECUTABLE_SUFFIX': '', + 'STATIC_LIB_PREFIX': 'lib', + 'STATIC_LIB_SUFFIX': '.a', + 'SHARED_LIB_PREFIX': 'lib', + + # Gyp expects the following variables to be expandable by the build + # system to the appropriate locations. Ninja prefers paths to be + # known at gyp time. To resolve this, introduce special + # variables starting with $! and $| (which begin with a $ so gyp knows it + # should be treated specially, but is otherwise an invalid + # ninja/shell variable) that are passed to gyp here but expanded + # before writing out into the target .ninja files; see NinjaWriter._ExpandSpecial. + # $! is used for variables that represent a path and that can only appear at + # the start of a string, while $| is used for variables that can appear + # anywhere in a string. + 'INTERMEDIATE_DIR': '$!INTERMEDIATE_DIR', + 'SHARED_INTERMEDIATE_DIR': '$!PRODUCT_DIR/gen', + 'PRODUCT_DIR': '$!PRODUCT_DIR', + 'CONFIGURATION_NAME': '$|CONFIGURATION_NAME', + + # Special variables that may be used by gyp 'rule' targets. + # We generate definitions for these variables on the fly when processing a + # rule. + 'RULE_INPUT_ROOT': '${root}', + 'RULE_INPUT_DIRNAME': '${dirname}', + 'RULE_INPUT_PATH': '${source}', + 'RULE_INPUT_EXT': '${ext}', + 'RULE_INPUT_NAME': '${name}', +} + +# Placates pylint. +generator_additional_non_configuration_keys = [] +generator_additional_path_sections = [] +generator_extra_sources_for_rules = [] +generator_filelist_paths = None + +generator_supports_multiple_toolsets = gyp.common.CrossCompileRequested() + + +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)) + +# module level API +def CalculateVariables(default_variables, params): + """Calculate additional variables for use in the build (called by gyp).""" + global generator_additional_non_configuration_keys + global generator_additional_path_sections + flavor = gyp.common.GetFlavor(params) + if flavor == 'mac': + default_variables.setdefault('OS', 'mac') + default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib') + default_variables.setdefault('SHARED_LIB_DIR', generator_default_variables['PRODUCT_DIR']) + default_variables.setdefault('LIB_DIR', generator_default_variables['PRODUCT_DIR']) + + # Copy additional generator configuration data from Xcode, which is shared + # by the Mac Ninja generator. + import gyp.generator.xcode as xcode_generator + generator_additional_non_configuration_keys = getattr(xcode_generator, 'generator_additional_non_configuration_keys', []) + generator_additional_path_sections = getattr(xcode_generator, 'generator_additional_path_sections', []) + global generator_extra_sources_for_rules + generator_extra_sources_for_rules = getattr(xcode_generator, 'generator_extra_sources_for_rules', []) + elif flavor == 'win': + exts = MSVS.TARGET_TYPE_EXT + default_variables.setdefault('OS', 'win') + default_variables['EXECUTABLE_SUFFIX'] = '.' + exts['executable'] + default_variables['STATIC_LIB_PREFIX'] = '' + default_variables['STATIC_LIB_SUFFIX'] = '.' + exts['static_library'] + default_variables['SHARED_LIB_PREFIX'] = '' + default_variables['SHARED_LIB_SUFFIX'] = '.' + exts['shared_library'] + + # 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) + default_variables.setdefault('SHARED_LIB_SUFFIX', '.so') + default_variables.setdefault('SHARED_LIB_DIR', os.path.join('$!PRODUCT_DIR', 'lib')) + default_variables.setdefault('LIB_DIR', os.path.join('$!PRODUCT_DIR', 'obj')) + + +# module level API +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): + """Open |path| for writing, creating directories if necessary.""" + gyp.common.EnsureDirExists(path) + return codecs.open(path, mode='w', encoding='utf-8') + + +def CommandWithWrapper(cmd, wrappers, prog): + wrapper = wrappers.get(cmd, '') + if wrapper: + return wrapper + ' ' + prog + return prog + + +def GetDefaultConcurrentLinks(): + """Returns a best-guess for a number of concurrent links.""" + pool_size = int(os.environ.get('GYP_LINK_CONCURRENCY', 0)) + if pool_size: + return pool_size + + if sys.platform in ('win32', 'cygwin'): + import ctypes + + class MEMORYSTATUSEX(ctypes.Structure): + _fields_ = [ + ("dwLength", ctypes.c_ulong), + ("dwMemoryLoad", ctypes.c_ulong), + ("ullTotalPhys", ctypes.c_ulonglong), + ("ullAvailPhys", ctypes.c_ulonglong), + ("ullTotalPageFile", ctypes.c_ulonglong), + ("ullAvailPageFile", ctypes.c_ulonglong), + ("ullTotalVirtual", ctypes.c_ulonglong), + ("ullAvailVirtual", ctypes.c_ulonglong), + ("sullAvailExtendedVirtual", ctypes.c_ulonglong), + ] + + stat = MEMORYSTATUSEX() + stat.dwLength = ctypes.sizeof(stat) + ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat)) + + # 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.environ.get('GYP_LINK_CONCURRENCY_MAX', 2 ** 32))) + return min(mem_limit, hard_cap) + elif sys.platform.startswith('linux'): + 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: + avail_bytes = int(subprocess.check_output(['sysctl', '-n', 'hw.memsize'])) + # A static library debug build of Chromium's unit_tests takes ~2.7GB, so + # 4GB per ld process allows for some more bloat. + return max(1, avail_bytes // (4 * (2 ** 30))) # total / 4GB + except ValueError: + return 1 + else: + # TODO(scottmg): Implement this for other platforms. + return 1 + + +def GetWinLinkRuleNameSuffix(embed_manifest): + """ + Returns the suffix used to select an appropriate linking rule depending on whether the manifest embedding is enabled. + """ + return '_embed' if embed_manifest else '' + + +def _AddWinLinkRules(master_ninja, embed_manifest): + """Adds link rules for Windows platform to |master_ninja|.""" + + def FullLinkCommand(ldcmd, out, binary_type): + resource_name = { + 'exe': '1', + 'dll': '2', + }[binary_type] + 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='$binary.rsp', + rspfile_content='$libs $in_newline $ldflags', + restat=True, + pool='link_pool') + master_ninja.rule('solink_module' + rule_name_suffix, + description=dlldesc, command=dllcmd, + rspfile='$binary.rsp', + rspfile_content='$libs $in_newline $ldflags', + 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 %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 $binary' % rule_name_suffix.upper(), command=exe_cmd, rspfile='$binary.rsp', rspfile_content='$in_newline $libs $ldflags', pool='link_pool') + + +def GenerateOutputForConfig(target_list, target_dicts, data, params, config_name): + options = params['options'] + flavor = gyp.common.GetFlavor(params) + generator_flags = params.get('generator_flags', OrderedDict()) + + # build_dir: relative path from source root to our output files. + # e.g. "out/Debug" + build_dir = os.path.normpath(os.path.join(ComputeOutputDir(params), config_name)) + + toplevel_build = os.path.join(options.toplevel_dir, build_dir) + + master_ninja_file = OpenOutput(os.path.join(toplevel_build, 'build.ninja')) + master_ninja_writer = ninja_syntax.Writer(master_ninja_file, width=250) + + # Put build-time support tools in out/{config_name}. + gyp.common.CopyTool(flavor, toplevel_build, generator_flags.get('mac_toolchain_dir')) + + # Grab make settings for CC/CXX. + # The rules are + # - The priority from low to high is gcc/g++, the 'make_global_settings' in + # gyp, the environment variable. + # - If there is no 'make_global_settings' for CC.host/CXX.host or + # 'CC_host'/'CXX_host' enviroment variable, cc_host/cxx_host should be set + # to cc/cxx. + if flavor == 'win': + 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 = 'cl.exe' + cxx = 'cl.exe' + ld = 'link.exe' + ld_host = '$ld' + ldxx = 'UNSET' + ldxx_host = 'UNSET' + else: + 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 + 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', []) + build_to_root = gyp.common.InvertRelativePath(build_dir, 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 key == 'CXX': + cxx = os.path.join(build_to_root, value) + if key == 'CC.host': + cc_host = os.path.join(build_to_root, value) + cc_host_global_setting = value + 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) + + # Support wrappers from environment variables too. + for key, value in os.environ.items(): + if key.lower().endswith('_wrapper'): + key_prefix = key[:-len('_wrapper')] + key_prefix = re.sub(r'\.HOST$', '.host', key_prefix) + wrappers[key_prefix] = os.path.join(build_to_root, value) + + mac_toolchain_dir = generator_flags.get('mac_toolchain_dir', None) + if mac_toolchain_dir: + wrappers['LINK'] = "export DEVELOPER_DIR='%s' &&" % mac_toolchain_dir + + if flavor == 'win': + gyp.msvs_emulation.GenerateEnvironmentFiles(toplevel_build, generator_flags) + + cc = GetEnvironFallback(['CC_target', 'CC'], cc) + master_ninja_writer.variable('cc', CommandWithWrapper('CC', wrappers, cc)) + cxx = GetEnvironFallback(['CXX_target', 'CXX'], cxx) + master_ninja_writer.variable('cxx', CommandWithWrapper('CXX', wrappers, cxx)) + + if flavor == 'win': + master_ninja_writer.variable('ld', ld) + master_ninja_writer.variable('idl', 'midl.exe') + master_ninja_writer.variable('ar', ar) + master_ninja_writer.variable('rc', 'rc.exe') + master_ninja_writer.variable('ml_x86', 'ml.exe') + master_ninja_writer.variable('ml_x64', 'ml64.exe') + master_ninja_writer.variable('mt', 'mt.exe') + else: + master_ninja_writer.variable('ld', CommandWithWrapper('LINK', wrappers, ld)) + master_ninja_writer.variable('ldxx', CommandWithWrapper('LINK', wrappers, ldxx)) + master_ninja_writer.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_writer.variable('nm', GetEnvironFallback(['NM_target', 'NM'], nm)) + master_ninja_writer.variable('readelf', GetEnvironFallback(['READELF_target', 'READELF'], readelf)) + + if generator_supports_multiple_toolsets: + if not cc_host: + cc_host = cc + if not cxx_host: + cxx_host = cxx + + master_ninja_writer.variable('ar_host', GetEnvironFallback(['AR_host'], ar_host)) + master_ninja_writer.variable('nm_host', GetEnvironFallback(['NM_host'], nm_host)) + master_ninja_writer.variable('readelf_host', GetEnvironFallback(['READELF_host'], readelf_host)) + cc_host = GetEnvironFallback(['CC_host'], cc_host) + cxx_host = GetEnvironFallback(['CXX_host'], cxx_host) + + # The environment variable could be used in 'make_global_settings', like + # ['CC.host', '$(CC)'] or ['CXX.host', '$(CXX)'], transform them here. + if '$(CC)' in cc_host and cc_host_global_setting: + cc_host = cc_host_global_setting.replace('$(CC)', cc) + if '$(CXX)' in cxx_host and cxx_host_global_setting: + cxx_host = cxx_host_global_setting.replace('$(CXX)', cxx) + master_ninja_writer.variable('cc_host', CommandWithWrapper('CC.host', wrappers, cc_host)) + master_ninja_writer.variable('cxx_host', CommandWithWrapper('CXX.host', wrappers, cxx_host)) + if flavor == 'win': + master_ninja_writer.variable('ld_host', ld_host) + else: + master_ninja_writer.variable('ld_host', CommandWithWrapper('LINK', wrappers, ld_host)) + master_ninja_writer.variable('ldxx_host', CommandWithWrapper('LINK', wrappers, ldxx_host)) + + master_ninja_writer.newline() + + master_ninja_writer.pool('link_pool', depth=GetDefaultConcurrentLinks()) + master_ninja_writer.newline() + + deps = 'msvc' if flavor == 'win' else 'gcc' + + if flavor != 'win': + master_ninja_writer.rule( + 'cc', + description='CC $out', + command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c ' + '$cflags_pch_c -c $in -o $out'), + depfile='$out.d', + deps=deps) + master_ninja_writer.rule( + 'cc_s', + description='CC $out', + command=('$cc $defines $includes $cflags $cflags_c ' + '$cflags_pch_c -c $in -o $out')) + master_ninja_writer.rule( + 'cxx', + description='CXX $out', + command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc ' + '$cflags_pch_cc -c $in -o $out'), + 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_c ') + cxx_command = ('ninja -t msvc -e $arch ' + + '-- ' + '$cxx /nologo /showIncludes /FC ' + '@$out.rsp /c $in /Fo$out /Fd$pdbname_cc ') + master_ninja_writer.rule( + 'cc', + description='CC $out', + command=cc_command, + rspfile='$out.rsp', + rspfile_content='$defines $includes $cflags $cflags_c', + deps=deps) + master_ninja_writer.rule( + 'cxx', + description='CXX $out', + command=cxx_command, + rspfile='$out.rsp', + rspfile_content='$defines $includes $cflags $cflags_cc', + deps=deps) + master_ninja_writer.rule( + 'idl', + description='IDL $in', + command=('%s gyp-win-tool midl-wrapper $arch $outdir ' + '$tlb $h $dlldata $iid $proxy $in ' + '$midl_includes $idlflags' % sys.executable)) + master_ninja_writer.rule( + 'rc', + description='RC $in', + # Note: $in must be last otherwise rc.exe complains. + command=('%s gyp-win-tool rc-wrapper ' + '$arch $rc $defines $resource_includes $rcflags /fo$out $in' % + sys.executable)) + master_ninja_writer.rule( + 'asm', + description='ASM $out', + command=('%s gyp-win-tool asm-wrapper ' + '$arch $asm $defines $includes $asmflags /c /Fo $out $in' % + sys.executable)) + + if flavor != 'mac' and flavor != 'win': + master_ninja_writer.rule('alink', description='AR $out', command='rm -f $out && $ar rcs $arflags $out $in') + master_ninja_writer.rule('alink_thin', description='AR $out', 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 + # dependencies when $lib changes only in non-public ways. + # 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 ; ' + '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\' \'; }')}) + + master_ninja_writer.rule( + 'solink', + description='SOLINK $lib', + restat=True, + 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_writer.rule( + 'solink_module', + description='SOLINK(module) $lib', + restat=True, + 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_writer.rule( + 'link', + description='LINK $out', + command=('$ld $ldflags -o $out ' + '-Wl,--start-group $in -Wl,--end-group $solibs $libs'), + pool='link_pool') + elif flavor == 'win': + master_ninja_writer.rule( + 'alink', + description='LIB $out', + 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_writer, embed_manifest=True) + _AddWinLinkRules(master_ninja_writer, embed_manifest=False) + else: + master_ninja_writer.rule( + 'objc', + description='OBJC $out', + command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_objc ' + '$cflags_pch_objc -c $in -o $out'), + depfile='$out.d', + deps=deps) + master_ninja_writer.rule( + 'objcxx', + description='OBJCXX $out', + command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_objcc ' + '$cflags_pch_objcc -c $in -o $out'), + depfile='$out.d', + deps=deps) + master_ninja_writer.rule( + 'alink', + description='LIBTOOL-STATIC $out, POSTBUILDS', + command='rm -f $out && ' + './gyp-mac-tool filter-libtool libtool $libtool_flags ' + '-static -o $out $in' + '$postbuilds') + master_ninja_writer.rule( + 'lipo', + description='LIPO $out, POSTBUILDS', + command='rm -f $out && lipo -create $in -output $out$postbuilds') + master_ninja_writer.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 ] || ' + # 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; ' + 'else ' + '%(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, + 'extract_toc': + '{ otool -l $lib | grep LC_ID_DYLIB -A 5; ' + 'nm -gP $lib | cut -f1-2 -d\' \' | grep -v U$$; true; }'}) + + solink_suffix = '@$link_file_list$postbuilds' + master_ninja_writer.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_writer.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') + + master_ninja_writer.rule( + 'solink_module', + description='SOLINK(module) $lib, POSTBUILDS', + restat=True, + command=mtime_preserving_solink_base % {'suffix': solink_suffix, + 'type': '-bundle'}, + rspfile='$link_file_list', + rspfile_content='$in $solibs $libs', + pool='link_pool') + master_ninja_writer.rule( + 'solink_module_notoc', + description='SOLINK(module) $lib, POSTBUILDS', + restat=True, + command=solink_base % {'suffix': solink_suffix, 'type': '-bundle'}, + rspfile='$link_file_list', + rspfile_content='$in $solibs $libs', + pool='link_pool') + + master_ninja_writer.rule( + 'link', + description='LINK $out, POSTBUILDS', + command=('$ld $ldflags -o $out ' + '$in $solibs $libs$postbuilds'), + pool='link_pool') + master_ninja_writer.rule( + '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_writer.rule( + 'copy_infoplist', + description='COPY INFOPLIST $in', + command='$env ./gyp-mac-tool copy-info-plist $in $out $binary $keys') + master_ninja_writer.rule( + 'merge_infoplist', + description='MERGE INFOPLISTS $in', + command='$env ./gyp-mac-tool merge-info-plist $out $in') + master_ninja_writer.rule( + 'compile_xcassets', + description='COMPILE XCASSETS $in', + command='$env ./gyp-mac-tool compile-xcassets $keys $in') + master_ninja_writer.rule( + 'compile_ios_framework_headers', + description='COMPILE HEADER MAPS AND COPY FRAMEWORK HEADERS $in', + command='$env ./gyp-mac-tool compile-ios-framework-header-map $out ' + '$framework $in && $env ./gyp-mac-tool ' + 'copy-ios-framework-headers $framework $copy_headers') + master_ninja_writer.rule( + 'mac_tool', + description='MACTOOL $mactool_cmd $in', + command='$env ./gyp-mac-tool $mactool_cmd $in $out $binary') + master_ninja_writer.rule( + 'package_framework', + description='PACKAGE FRAMEWORK $out, POSTBUILDS', + command='./gyp-mac-tool package-framework $out $version$postbuilds ' + '&& touch $out') + master_ninja_writer.rule( + 'package_ios_framework', + description='PACKAGE IOS FRAMEWORK $out, POSTBUILDS', + command='./gyp-mac-tool package-ios-framework $out $postbuilds ' + '&& touch $out') + if flavor == 'win': + master_ninja_writer.rule('stamp', description='STAMP $out', command='%s gyp-win-tool stamp $out' % sys.executable) + else: + master_ninja_writer.rule('stamp', description='STAMP $out', command='${postbuilds}touch $out') + if flavor == 'win': + master_ninja_writer.rule('copy', description='COPY $in $out', command='%s gyp-win-tool recursive-mirror $in $out' % sys.executable) + elif flavor == 'zos': + master_ninja_writer.rule('copy', description='COPY $in $out', command='rm -rf $out && cp -fRP $in $out') + else: + master_ninja_writer.rule('copy', description='COPY $in $out', command='ln -f $in $out 2>/dev/null || (rm -rf $out && cp -af $in $out)') + master_ninja_writer.newline() + + all_targets = set() + for build_file in params['build_files']: + for target in gyp.common.AllTargets(target_list, target_dicts, os.path.normpath(build_file)): + all_targets.add(target) + all_outputs = set() + + # target_outputs is a map from qualified target name to a Target object. + target_outputs = {} + # target_short_names is a map from target short name to a list of Target + # objects. + target_short_names = {} + + # 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 + build_file, name, toolset = gyp.common.ParseQualifiedTarget(qualified_target) + + 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. %s vs. %s" % (this_make_global_settings, make_global_settings)) + + spec = target_dicts[qualified_target] + if flavor == 'mac': + gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec) + + # If build_file is a symlink, we must not follow it because there's a chance + # it could point to a path above toplevel_dir, and we cannot correctly deal + # with that case at the moment. + build_file = gyp.common.RelativePath(build_file, options.toplevel_dir, False) + + qualified_target_for_hash = gyp.common.QualifiedTarget(build_file, name, toolset) + qualified_target_for_hash = qualified_target_for_hash.encode('utf-8') + hash_for_rules = hashlib.md5(qualified_target_for_hash).hexdigest() + + base_path = os.path.dirname(build_file) + obj = 'obj' + if toolset != 'target': + obj += '.' + toolset + output_file = os.path.join(obj, base_path, name + '.ninja') + + ninja_output = StringIO() + from gyp.NinjaWriter import NinjaWriter + writer = NinjaWriter(hash_for_rules, target_outputs, base_path, build_dir, ninja_output, toplevel_build, output_file, flavor, spec, generator_flags, config_name, options.toplevel_dir) + + target = writer.WriteSpec() + + if ninja_output.tell() > 0: + # Only create files for ninja files that actually have contents. + with OpenOutput(os.path.join(toplevel_build, output_file)) as ninja_file: + ninja_file.write(ninja_output.getvalue()) + ninja_output.close() + master_ninja_writer.subninja(output_file) + + if target: + if name != target.FinalOutput() and spec['toolset'] == 'target': + target_short_names.setdefault(name, []).append(target) + 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 + # "build chrome" case as well as the gyp tests, which expect to be + # able to run actions and build libraries by their short name. + master_ninja_writer.newline() + master_ninja_writer.comment('Short names for targets.') + for short_name in sorted(target_short_names): + master_ninja_writer.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_writer.newline() + master_ninja_writer.comment('Empty targets (output for completeness).') + for name in sorted(empty_target_names): + master_ninja_writer.build(name, 'phony') + + if all_outputs: + master_ninja_writer.newline() + master_ninja_writer.build('all', 'phony', sorted(all_outputs)) + master_ninja_writer.default(generator_flags.get('default_target', 'all')) + + master_ninja_file.close() + + +def PerformBuild(_, configurations, params): + options = params['options'] + for config in configurations: + builddir = os.path.join(options.toplevel_dir, 'out', config) + arguments = ['ninja', '-C', builddir] + print('Building [%s]: %s' % (config, arguments)) + subprocess.check_call(arguments) + + +def GenerateOutput(target_list, target_dicts, data, params): + user_config = params['generator_flags'].get('config', None) + if gyp.common.GetFlavor(params) == 'win': + target_list, target_dicts = MSVS.ShardTargets(target_list, target_dicts) + target_list, target_dicts = MSVS.InsertLargePdbShims(target_list, target_dicts, generator_default_variables) + elif gyp.common.GetFlavor(params) == 'mac': + # Update target_dicts for iOS device builds. + target_dicts = gyp.xcode_emulation.CloneConfigurationForDeviceAndEmulator(target_dicts) + + if user_config: + GenerateOutputForConfig(target_list, target_dicts, data, params, user_config) + else: + config_names = target_dicts[target_list[0]]['configurations'] + for config_name in config_names: + GenerateOutputForConfig(target_list, target_dicts, data, params, config_name) diff --git a/tools/gyp/pylib/gyp/generator/xcode.py b/tools/gyp/gyp/generator/xcode.py similarity index 93% rename from tools/gyp/pylib/gyp/generator/xcode.py rename to tools/gyp/gyp/generator/xcode.py index db99d6ab81ed5c..0bdc67f9893056 100644 --- a/tools/gyp/pylib/gyp/generator/xcode.py +++ b/tools/gyp/gyp/generator/xcode.py @@ -2,10 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +from __future__ import print_function + import filecmp import gyp.common -import gyp.xcodeproj_file -import gyp.xcode_ninja +import gyp.generator.xcodeproj_file +import gyp.generator.xcode_ninja import errno import os import sys @@ -98,11 +100,11 @@ ]) def CreateXCConfigurationList(configuration_names): - xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []}) + xccl = gyp.generator.xcodeproj_file.XCConfigurationList({'buildConfigurations': []}) if len(configuration_names) == 0: configuration_names = ['Default'] for configuration_name in configuration_names: - xcbc = gyp.xcodeproj_file.XCBuildConfiguration({ + xcbc = gyp.generator.xcodeproj_file.XCBuildConfiguration({ 'name': configuration_name}) xccl.AppendProperty('buildConfigurations', xcbc) xccl.SetProperty('defaultConfigurationName', configuration_names[0]) @@ -113,13 +115,13 @@ class XcodeProject(object): def __init__(self, gyp_path, path, build_file_dict): self.gyp_path = gyp_path self.path = path - self.project = gyp.xcodeproj_file.PBXProject(path=path) + self.project = gyp.generator.xcodeproj_file.PBXProject(path=path) projectDirPath = gyp.common.RelativePath( os.path.dirname(os.path.abspath(self.gyp_path)), os.path.dirname(path) or '.') self.project.SetProperty('projectDirPath', projectDirPath) self.project_file = \ - gyp.xcodeproj_file.XCProjectFile({'rootObject': self.project}) + gyp.generator.xcodeproj_file.XCProjectFile({'rootObject': self.project}) self.build_file_dict = build_file_dict # TODO(mark): add destructor that cleans up self.path if created_dir is @@ -129,7 +131,7 @@ def __init__(self, gyp_path, path, build_file_dict): try: os.makedirs(self.path) self.created_dir = True - except OSError, e: + except OSError as e: if e.errno != errno.EEXIST: raise @@ -183,7 +185,7 @@ def Finalize1(self, xcode_targets, serialize_all_tests): # the tree tree view for UI display. # Any values set globally are applied to all configurations, then any # per-configuration values are applied. - for xck, xcv in self.build_file_dict.get('xcode_settings', {}).iteritems(): + for xck, xcv in self.build_file_dict.get('xcode_settings', {}).items(): xccl.SetBuildSetting(xck, xcv) if 'xcode_config_file' in self.build_file_dict: config_ref = self.project.AddOrGetFileInRootGroup( @@ -197,7 +199,7 @@ def Finalize1(self, xcode_targets, serialize_all_tests): if build_file_configuration_named: xcc = xccl.ConfigurationNamed(config_name) for xck, xcv in build_file_configuration_named.get('xcode_settings', - {}).iteritems(): + {}).items(): xcc.SetBuildSetting(xck, xcv) if 'xcode_config_file' in build_file_configuration_named: config_ref = self.project.AddOrGetFileInRootGroup( @@ -254,7 +256,7 @@ def Finalize1(self, xcode_targets, serialize_all_tests): # Make a target to run something. It should have one # dependency, the parent xcode target. xccl = CreateXCConfigurationList(configurations) - run_target = gyp.xcodeproj_file.PBXAggregateTarget({ + run_target = gyp.generator.xcodeproj_file.PBXAggregateTarget({ 'name': 'Run ' + target_name, 'productName': xcode_target.GetProperty('productName'), 'buildConfigurationList': xccl, @@ -266,14 +268,14 @@ def Finalize1(self, xcode_targets, serialize_all_tests): script = '' if command.get('working_directory'): script = script + 'cd "%s"\n' % \ - gyp.xcodeproj_file.ConvertVariablesToShellSyntax( + gyp.generator.xcodeproj_file.ConvertVariablesToShellSyntax( command.get('working_directory')) if command.get('environment'): script = script + "\n".join( ['export %s="%s"' % - (key, gyp.xcodeproj_file.ConvertVariablesToShellSyntax(val)) - for (key, val) in command.get('environment').iteritems()]) + "\n" + (key, gyp.generator.xcodeproj_file.ConvertVariablesToShellSyntax(val)) + for (key, val) in command.get('environment').items()]) + "\n" # Some test end up using sockets, files on disk, etc. and can get # confused if more then one test runs at a time. The generator @@ -293,10 +295,10 @@ def Finalize1(self, xcode_targets, serialize_all_tests): # with an error, and fixup variable references to be shell # syntax instead of xcode syntax. script = script + 'exec ' + command_prefix + '%s\nexit 1\n' % \ - gyp.xcodeproj_file.ConvertVariablesToShellSyntax( + gyp.generator.xcodeproj_file.ConvertVariablesToShellSyntax( gyp.common.EncodePOSIXShellList(command.get('action'))) - ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ + ssbp = gyp.generator.xcodeproj_file.PBXShellScriptBuildPhase({ 'shellScript': script, 'showEnvVarsInLog': 0, }) @@ -328,7 +330,7 @@ def Finalize1(self, xcode_targets, serialize_all_tests): # time will build everything by default. if len(targets_for_all) > 1 and not has_custom_all: xccl = CreateXCConfigurationList(configurations) - all_target = gyp.xcodeproj_file.PBXAggregateTarget( + all_target = gyp.generator.xcodeproj_file.PBXAggregateTarget( { 'buildConfigurationList': xccl, 'name': 'All', @@ -346,7 +348,7 @@ def Finalize1(self, xcode_targets, serialize_all_tests): # The same, but for run_test_targets. if len(run_test_targets) > 1: xccl = CreateXCConfigurationList(configurations) - run_all_tests_target = gyp.xcodeproj_file.PBXAggregateTarget( + run_all_tests_target = gyp.generator.xcodeproj_file.PBXAggregateTarget( { 'buildConfigurationList': xccl, 'name': 'Run All Tests', @@ -378,7 +380,7 @@ def Finalize2(self, xcode_targets, xcode_target_to_target_dict): qualified_target = gyp.common.QualifiedTarget(self.gyp_path, tgt_name, toolset) xcode_target = xcode_targets[qualified_target] - if isinstance(xcode_target, gyp.xcodeproj_file.PBXAggregateTarget): + if isinstance(xcode_target, gyp.generator.xcodeproj_file.PBXAggregateTarget): # Collect all the run test targets. all_run_tests = [] pbxtds = xcode_target.GetProperty('dependencies') @@ -391,7 +393,7 @@ def Finalize2(self, xcode_targets, xcode_target_to_target_dict): # Directly depend on all the runners as they depend on the target # that builds them. if len(all_run_tests) > 0: - run_all_target = gyp.xcodeproj_file.PBXAggregateTarget({ + run_all_target = gyp.generator.xcodeproj_file.PBXAggregateTarget({ 'name': 'Run %s Tests' % tgt_name, 'productName': tgt_name, }, @@ -444,7 +446,7 @@ def Write(self): dir=self.path) try: - output_file = os.fdopen(output_fd, 'wb') + output_file = os.fdopen(output_fd, 'w') self.project_file.Print(output_file) output_file.close() @@ -454,7 +456,7 @@ def Write(self): same = False try: same = filecmp.cmp(pbxproj_path, new_pbxproj_path, False) - except OSError, e: + except OSError as e: if e.errno != errno.ENOENT: raise @@ -473,10 +475,10 @@ def Write(self): # # No way to get the umask without setting a new one? Set a safe one # and then set it back to the old value. - umask = os.umask(077) + umask = os.umask(0o77) os.umask(umask) - os.chmod(new_pbxproj_path, 0666 & ~umask) + os.chmod(new_pbxproj_path, 0o666 & ~umask) os.rename(new_pbxproj_path, pbxproj_path) except Exception: @@ -566,7 +568,7 @@ def EscapeXcodeDefine(s): def PerformBuild(data, configurations, params): options = params['options'] - for build_file, build_file_dict in data.iteritems(): + for build_file, build_file_dict in data.items(): (build_file_root, build_file_ext) = os.path.splitext(build_file) if build_file_ext != '.gyp': continue @@ -577,7 +579,7 @@ def PerformBuild(data, configurations, params): for config in configurations: arguments = ['xcodebuild', '-project', xcodeproj_path] arguments += ['-configuration', config] - print "Building [%s]: %s" % (config, arguments) + print("Building [%s]: %s" % (config, arguments)) subprocess.check_call(arguments) @@ -606,7 +608,7 @@ def GenerateOutput(target_list, target_dicts, data, params): ninja_wrapper = params.get('flavor') == 'ninja' if ninja_wrapper: (target_list, target_dicts, data) = \ - gyp.xcode_ninja.CreateWrapper(target_list, target_dicts, data, params) + gyp.generator.xcode_ninja.CreateWrapper(target_list, target_dicts, data, params) options = params['options'] generator_flags = params.get('generator_flags', {}) @@ -625,7 +627,7 @@ def GenerateOutput(target_list, target_dicts, data, params): skip_excluded_files = \ not generator_flags.get('xcode_list_excluded_files', True) xcode_projects = {} - for build_file, build_file_dict in data.iteritems(): + for build_file, build_file_dict in data.items(): (build_file_root, build_file_ext) = os.path.splitext(build_file) if build_file_ext != '.gyp': continue @@ -651,7 +653,7 @@ def GenerateOutput(target_list, target_dicts, data, params): # Add gyp/gypi files to project if not generator_flags.get('standalone'): main_group = pbxp.GetProperty('mainGroup') - build_group = gyp.xcodeproj_file.PBXGroup({'name': 'Build'}) + build_group = gyp.generator.xcodeproj_file.PBXGroup({'name': 'Build'}) main_group.AppendChild(build_group) for included_file in build_file_dict['included_files']: build_group.AddOrGetFileByPath(included_file, False) @@ -659,8 +661,7 @@ def GenerateOutput(target_list, target_dicts, data, params): xcode_targets = {} xcode_target_to_target_dict = {} for qualified_target in target_list: - [build_file, target_name, toolset] = \ - gyp.common.ParseQualifiedTarget(qualified_target) + [build_file, target_name, toolset] = gyp.common.ParseQualifiedTarget(qualified_target) spec = target_dicts[qualified_target] if spec['toolset'] != 'target': @@ -710,7 +711,7 @@ def GenerateOutput(target_list, target_dicts, data, params): type = spec['type'] is_xctest = int(spec.get('mac_xctest_bundle', 0)) is_xcuitest = int(spec.get('mac_xcuitest_bundle', 0)) - is_bundle = int(spec.get('mac_bundle', 0)) or is_xctest + is_bundle = int(spec.get('mac_bundle', 0)) or is_xctest or is_xcuitest 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)) @@ -741,15 +742,15 @@ def GenerateOutput(target_list, target_dicts, data, params): elif is_bundle: type_bundle_key += '+bundle' - xctarget_type = gyp.xcodeproj_file.PBXNativeTarget + xctarget_type = gyp.generator.xcodeproj_file.PBXNativeTarget try: target_properties['productType'] = _types[type_bundle_key] - except KeyError, e: + except KeyError as e: gyp.common.ExceptionAppend(e, "-- unknown product type while " "writing target %s" % target_name) raise else: - xctarget_type = gyp.xcodeproj_file.PBXAggregateTarget + xctarget_type = gyp.generator.xcodeproj_file.PBXAggregateTarget assert not is_bundle, ( 'mac_bundle targets cannot have type none (target "%s")' % target_name) @@ -797,8 +798,8 @@ def GenerateOutput(target_list, target_dicts, data, params): support_target_properties['productName'] = \ target_product_name + ' Support' support_xct = \ - gyp.xcodeproj_file.PBXAggregateTarget(support_target_properties, - parent=pbxp) + gyp.generator.xcodeproj_file.PBXAggregateTarget(support_target_properties, + parent=pbxp) pbxp.AppendProperty('targets', support_xct) xct.AddDependency(support_xct) # Hang the support target off the main target so it can be tested/found @@ -825,8 +826,8 @@ def GenerateOutput(target_list, target_dicts, data, params): # Convert Xcode-type variable references to sh-compatible environment # variable references. - message_sh = gyp.xcodeproj_file.ConvertVariablesToShellSyntax(message) - action_string_sh = gyp.xcodeproj_file.ConvertVariablesToShellSyntax( + message_sh = gyp.generator.xcodeproj_file.ConvertVariablesToShellSyntax(message) + action_string_sh = gyp.generator.xcodeproj_file.ConvertVariablesToShellSyntax( action_string) script = '' @@ -836,7 +837,7 @@ def GenerateOutput(target_list, target_dicts, data, params): # Be sure the script runs in exec, and that if exec fails, the script # exits signalling an error. script += 'exec ' + action_string_sh + '\nexit 1\n' - ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ + ssbp = gyp.generator.xcodeproj_file.PBXShellScriptBuildPhase({ 'inputPaths': action['inputs'], 'name': 'Action "' + action['action_name'] + '"', 'outputPaths': action['outputs'], @@ -1016,22 +1017,21 @@ def GenerateOutput(target_list, target_dicts, data, params): makefile_name) # TODO(mark): try/close? Write to a temporary file and swap it only # if it's got changes? - makefile = open(makefile_path, 'wb') + makefile = open(makefile_path, 'w') # make will build the first target in the makefile by default. By # convention, it's called "all". List all (or at least one) # concrete output for each rule source as a prerequisite of the "all" # target. makefile.write('all: \\\n') - for concrete_output_index in \ - xrange(0, len(concrete_outputs_by_rule_source)): + for concrete_output_index, concrete_output_by_rule_source in \ + enumerate(concrete_outputs_by_rule_source): # Only list the first (index [0]) concrete output of each input # in the "all" target. Otherwise, a parallel make (-j > 1) would # attempt to process each input multiple times simultaneously. # Otherwise, "all" could just contain the entire list of # concrete_outputs_all. - concrete_output = \ - concrete_outputs_by_rule_source[concrete_output_index][0] + concrete_output = concrete_output_by_rule_source[0] if concrete_output_index == len(concrete_outputs_by_rule_source) - 1: eol = '' else: @@ -1047,8 +1047,8 @@ def GenerateOutput(target_list, target_dicts, data, params): # rule source. Collect the names of the directories that are # required. concrete_output_dirs = [] - for concrete_output_index in xrange(0, len(concrete_outputs)): - concrete_output = concrete_outputs[concrete_output_index] + for concrete_output_index, concrete_output in \ + enumerate(concrete_outputs): if concrete_output_index == 0: bol = '' else: @@ -1066,8 +1066,7 @@ def GenerateOutput(target_list, target_dicts, data, params): # the set of additional rule inputs, if any. prerequisites = [rule_source] prerequisites.extend(rule.get('inputs', [])) - for prerequisite_index in xrange(0, len(prerequisites)): - prerequisite = prerequisites[prerequisite_index] + for prerequisite_index, prerequisite in enumerate(prerequisites): if prerequisite_index == len(prerequisites) - 1: eol = '' else: @@ -1094,17 +1093,6 @@ def GenerateOutput(target_list, target_dicts, data, params): # work if there ever was a concrete output that had an input-dependent # variable anywhere other than in the leaf position. - # Don't declare any inputPaths or outputPaths. If they're present, - # Xcode will provide a slight optimization by only running the script - # phase if any output is missing or outdated relative to any input. - # Unfortunately, it will also assume that all outputs are touched by - # the script, and if the outputs serve as files in a compilation - # phase, they will be unconditionally rebuilt. Since make might not - # rebuild everything that could be declared here as an output, this - # extra compilation activity is unnecessary. With inputPaths and - # outputPaths not supplied, make will always be called, but it knows - # enough to not do anything when everything is up-to-date. - # To help speed things up, pass -j COUNT to make so it does some work # in parallel. Don't use ncpus because Xcode will build ncpus targets # in parallel and if each target happens to have a rules step, there @@ -1119,8 +1107,10 @@ def GenerateOutput(target_list, target_dicts, data, params): exec xcrun make -f "${PROJECT_FILE_PATH}/%s" -j "${JOB_COUNT}" exit 1 """ % makefile_name - ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ + ssbp = gyp.generator.xcodeproj_file.PBXShellScriptBuildPhase({ + 'inputPaths': rule['rule_sources'], 'name': 'Rule "' + rule['rule_name'] + '"', + 'outputPaths': concrete_outputs_all, 'shellScript': script, 'showEnvVarsInLog': 0, }) @@ -1188,7 +1178,7 @@ def GenerateOutput(target_list, target_dicts, data, params): # they'll wind up with ID collisions. pbxcp = pbxcp_dict.get(dest, None) if pbxcp is None: - pbxcp = gyp.xcodeproj_file.PBXCopyFilesBuildPhase({ + pbxcp = gyp.generator.xcodeproj_file.PBXCopyFilesBuildPhase({ 'name': 'Copy to ' + copy_group['destination'] }, parent=xct) @@ -1232,7 +1222,7 @@ def GenerateOutput(target_list, target_dicts, data, params): # sufficient to ensure proper ordering in all cases. With an input # declared but no outputs, the script step should run every time, as # desired. - ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ + ssbp = gyp.generator.xcodeproj_file.PBXShellScriptBuildPhase({ 'inputPaths': ['$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_PATH)'], 'name': 'Postbuild "' + postbuild['postbuild_name'] + '"', 'shellScript': script, @@ -1288,7 +1278,7 @@ def GenerateOutput(target_list, target_dicts, data, params): set_define = EscapeXcodeDefine(define) xcbc.AppendBuildSetting('GCC_PREPROCESSOR_DEFINITIONS', set_define) if 'xcode_settings' in configuration: - for xck, xcv in configuration['xcode_settings'].iteritems(): + for xck, xcv in configuration['xcode_settings'].items(): xcbc.SetBuildSetting(xck, xcv) if 'xcode_config_file' in configuration: config_ref = pbxp.AddOrGetFileInRootGroup( @@ -1296,7 +1286,7 @@ def GenerateOutput(target_list, target_dicts, data, params): xcbc.SetBaseConfiguration(config_ref) build_files = [] - for build_file, build_file_dict in data.iteritems(): + for build_file, build_file_dict in data.items(): if build_file.endswith('.gyp'): build_files.append(build_file) diff --git a/tools/gyp/pylib/gyp/xcode_ninja.py b/tools/gyp/gyp/generator/xcode_ninja.py similarity index 98% rename from tools/gyp/pylib/gyp/xcode_ninja.py rename to tools/gyp/gyp/generator/xcode_ninja.py index bc76ffff4e9b58..1d71b8c5f89006 100644 --- a/tools/gyp/pylib/gyp/xcode_ninja.py +++ b/tools/gyp/gyp/generator/xcode_ninja.py @@ -28,7 +28,7 @@ def _WriteWorkspace(main_gyp, sources_gyp, params): workspace_path = os.path.join(options.generator_output, workspace_path) try: os.makedirs(workspace_path) - except OSError, e: + except OSError as e: if e.errno != errno.EEXIST: raise output_string = '\n' + \ @@ -85,7 +85,7 @@ def _TargetFromSpec(old_spec, params): "%s/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)" % ninja_toplevel if 'configurations' in old_spec: - for config in old_spec['configurations'].iterkeys(): + for config in old_spec['configurations'].keys(): old_xcode_settings = \ old_spec['configurations'][config].get('xcode_settings', {}) if 'IPHONEOS_DEPLOYMENT_TARGET' in old_xcode_settings: @@ -167,7 +167,7 @@ def CreateWrapper(target_list, target_dicts, data, params): params: Dict of global options for gyp. """ orig_gyp = params['build_files'][0] - for gyp_name, gyp_dict in data.iteritems(): + for gyp_name, gyp_dict in data.items(): if gyp_name == orig_gyp: depth = gyp_dict['_DEPTH'] @@ -238,7 +238,7 @@ def CreateWrapper(target_list, target_dicts, data, params): not generator_flags.get('xcode_ninja_list_excluded_files', True) sources = [] - for target, target_dict in target_dicts.iteritems(): + for target, target_dict in target_dicts.items(): base = os.path.dirname(target) files = target_dict.get('sources', []) + \ target_dict.get('mac_bundle_resources', []) diff --git a/tools/gyp/pylib/gyp/xcodeproj_file.py b/tools/gyp/gyp/generator/xcodeproj_file.py similarity index 98% rename from tools/gyp/pylib/gyp/xcodeproj_file.py rename to tools/gyp/gyp/generator/xcodeproj_file.py index e69235f7241ffe..544b94d1347ba8 100644 --- a/tools/gyp/pylib/gyp/xcodeproj_file.py +++ b/tools/gyp/gyp/generator/xcodeproj_file.py @@ -136,24 +136,30 @@ Strings of class unicode are handled properly and encoded in UTF-8 when a project file is output. """ - -import gyp.common +from functools import cmp_to_key import posixpath import re import struct import sys +import gyp.common + # hashlib is supplied as of Python 2.5 as the replacement interface for sha # and other secure hashes. In 2.6, sha is deprecated. Import hashlib if # available, avoiding a deprecation warning under 2.6. Import sha otherwise, # preserving 2.4 compatibility. try: - import hashlib - _new_sha1 = hashlib.sha1 + from hashlib import sha1 as sha except ImportError: - import sha - _new_sha1 = sha.new + # noinspection PyUnresolvedReferences,PyCompatibility + from sha import new as sha + +if 'basestring' not in __builtins__: + basestring = str +if 'cmp' not in __builtins__: + def cmp(a, b): + return (a > b) - (a < b) # See XCObject._EncodeString. This pattern is used to determine when a string # can be printed unquoted. Strings that match this pattern may be printed @@ -314,7 +320,7 @@ def Copy(self): """ that = self.__class__(id=self.id, parent=self.parent) - for key, value in self._properties.iteritems(): + for key, value in self._properties.items(): is_strong = self._schema[key][2] if isinstance(value, XCObject): @@ -324,8 +330,7 @@ def Copy(self): that._properties[key] = new_value else: that._properties[key] = value - elif isinstance(value, str) or isinstance(value, unicode) or \ - isinstance(value, int): + elif isinstance(value, basestring) or isinstance(value, int): that._properties[key] = value elif isinstance(value, list): if is_strong: @@ -422,7 +427,7 @@ def _HashUpdate(hash, data): hash.update(data) if seed_hash is None: - seed_hash = _new_sha1() + seed_hash = sha() hash = seed_hash.copy() @@ -449,10 +454,10 @@ def _HashUpdate(hash, data): # is 160 bits. Instead of throwing out 64 bits of the digest, xor them # into the portion that gets used. assert hash.digest_size % 4 == 0 - digest_int_count = hash.digest_size / 4 + digest_int_count = hash.digest_size // 4 digest_ints = struct.unpack('>' + 'I' * digest_int_count, hash.digest()) id_ints = [0, 0, 0] - for index in xrange(0, digest_int_count): + for index in range(0, digest_int_count): id_ints[index % 3] ^= digest_ints[index] self.id = '%08X%08X%08X' % tuple(id_ints) @@ -475,7 +480,7 @@ def Children(self): """Returns a list of all of this object's owned (strong) children.""" children = [] - for property, attributes in self._schema.iteritems(): + for property, attributes in self._schema.items(): (is_list, property_type, is_strong) = attributes[0:3] if is_strong and property in self._properties: if not is_list: @@ -603,7 +608,12 @@ def _XCPrintableValue(self, tabs, value, flatten_list=False): comment = value.Comment() elif isinstance(value, str): printable += self._EncodeString(value) - elif isinstance(value, unicode): + # A python3 compatible way of saying isinstance(value, unicode). + # basestring is str in python3 so this is equivalent to the above + # isinstance. Thus if it failed above it will fail here. + # In python2 we test against str and unicode at this point. str has already + # failed in the above isinstance so we test against unicode. + elif isinstance(value, basestring): printable += self._EncodeString(value.encode('utf-8')) elif isinstance(value, int): printable += str(value) @@ -622,7 +632,7 @@ def _XCPrintableValue(self, tabs, value, flatten_list=False): printable += end_tabs + ')' elif isinstance(value, dict): printable = '{' + sep - for item_key, item_value in sorted(value.iteritems()): + for item_key, item_value in sorted(value.items()): printable += element_tabs + \ self._XCPrintableValue(tabs + 1, item_key, flatten_list) + ' = ' + \ self._XCPrintableValue(tabs + 1, item_value, flatten_list) + ';' + \ @@ -691,7 +701,7 @@ def _XCKVPrint(self, file, tabs, key, value): printable_value[0] == '"' and printable_value[-1] == '"': printable_value = printable_value[1:-1] printable += printable_key + ' = ' + printable_value + ';' + after_kv - except TypeError, e: + except TypeError as e: gyp.common.ExceptionAppend(e, 'while printing key "%s"' % key) raise @@ -730,7 +740,7 @@ def Print(self, file=sys.stdout): self._XCKVPrint(file, 3, 'isa', self.__class__.__name__) # The remaining elements of an object dictionary are sorted alphabetically. - for property, value in sorted(self._properties.iteritems()): + for property, value in sorted(self._properties.items()): self._XCKVPrint(file, 3, property, value) # End the object. @@ -752,7 +762,7 @@ def UpdateProperties(self, properties, do_copy=False): if properties is None: return - for property, value in properties.iteritems(): + for property, value in properties.items(): # Make sure the property is in the schema. if not property in self._schema: raise KeyError(property + ' not in ' + self.__class__.__name__) @@ -766,7 +776,7 @@ def UpdateProperties(self, properties, do_copy=False): ' 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): + not (isinstance(item, basestring) and property_type == str): # Accept unicode where str is specified. str is treated as # UTF-8-encoded. raise TypeError( @@ -774,7 +784,7 @@ def UpdateProperties(self, properties, do_copy=False): ' must be ' + property_type.__name__ + ', not ' + \ item.__class__.__name__) elif not isinstance(value, property_type) and \ - not (value.__class__ == unicode and property_type == str): + not (isinstance(value, basestring) and property_type == str): # Accept unicode where str is specified. str is treated as # UTF-8-encoded. raise TypeError( @@ -788,8 +798,7 @@ def UpdateProperties(self, properties, do_copy=False): self._properties[property] = value.Copy() else: self._properties[property] = value - elif isinstance(value, str) or isinstance(value, unicode) or \ - isinstance(value, int): + elif isinstance(value, basestring) or isinstance(value, int): self._properties[property] = value elif isinstance(value, list): if is_strong: @@ -865,7 +874,7 @@ def VerifyHasRequiredProperties(self): # TODO(mark): A stronger verification mechanism is needed. Some # subclasses need to perform validation beyond what the schema can enforce. - for property, attributes in self._schema.iteritems(): + for property, attributes in self._schema.items(): (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) @@ -875,7 +884,7 @@ def _SetDefaultsFromSchema(self): overwrite properties that have already been set.""" defaults = {} - for property, attributes in self._schema.iteritems(): + for property, attributes in self._schema.items(): (is_list, property_type, is_strong, is_required) = attributes[0:4] if is_required and len(attributes) >= 5 and \ not property in self._properties: @@ -1426,8 +1435,8 @@ def PathHashables(self): xche = self while xche != None and isinstance(xche, XCHierarchicalElement): xche_hashables = xche.Hashables() - for index in xrange(0, len(xche_hashables)): - hashables.insert(index, xche_hashables[index]) + for index, xche_hashable in enumerate(xche_hashables): + hashables.insert(index, xche_hashable) xche = xche.parent return hashables @@ -2204,8 +2213,8 @@ class XCTarget(XCRemoteObject): 'productName': [0, str, 0, 1], }) - def __init__(self, properties=None, id=None, parent=None, - force_outdir=None, force_prefix=None, force_extension=None): + # noinspection PyUnusedLocal + def __init__(self, properties=None, id=None, parent=None, force_outdir=None, force_prefix=None, force_extension=None): # super XCRemoteObject.__init__(self, properties, id, parent) @@ -2265,12 +2274,10 @@ def GetBuildSetting(self, key): return self._properties['buildConfigurationList'].GetBuildSetting(key) def SetBuildSetting(self, key, value): - return self._properties['buildConfigurationList'].SetBuildSetting(key, \ - value) + return self._properties['buildConfigurationList'].SetBuildSetting(key, value) def AppendBuildSetting(self, key, value): - return self._properties['buildConfigurationList'].AppendBuildSetting(key, \ - value) + return self._properties['buildConfigurationList'].AppendBuildSetting(key, value) def DelBuildSetting(self, key): return self._properties['buildConfigurationList'].DelBuildSetting(key) @@ -2468,8 +2475,7 @@ def HeadersPhase(self): # The headers phase should come before the resources, sources, and # frameworks phases, if any. insert_at = len(self._properties['buildPhases']) - for index in xrange(0, len(self._properties['buildPhases'])): - phase = self._properties['buildPhases'][index] + for index, phase in enumerate(self._properties['buildPhases']): if isinstance(phase, PBXResourcesBuildPhase) or \ isinstance(phase, PBXSourcesBuildPhase) or \ isinstance(phase, PBXFrameworksBuildPhase): @@ -2489,8 +2495,7 @@ def ResourcesPhase(self): # The resources phase should come before the sources and frameworks # phases, if any. insert_at = len(self._properties['buildPhases']) - for index in xrange(0, len(self._properties['buildPhases'])): - phase = self._properties['buildPhases'][index] + for index, phase in enumerate(self._properties['buildPhases']): if isinstance(phase, PBXSourcesBuildPhase) or \ isinstance(phase, PBXFrameworksBuildPhase): insert_at = index @@ -2528,9 +2533,9 @@ def AddDependency(self, other): 'productType' in self._properties and \ self._properties['productType'] != static_library_type and \ 'productType' in other._properties and \ - (other._properties['productType'] == static_library_type or \ - ((other._properties['productType'] == shared_library_type or \ - other._properties['productType'] == framework_type) and \ + (other._properties['productType'] == static_library_type or + ((other._properties['productType'] == shared_library_type or + other._properties['productType'] == framework_type) and ((not other.HasBuildSetting('MACH_O_TYPE')) or other.GetBuildSetting('MACH_O_TYPE') != 'mh_bundle'))): @@ -2568,8 +2573,7 @@ class PBXProject(XCContainerPortal): _schema = XCContainerPortal._schema.copy() _schema.update({ 'attributes': [0, dict, 0, 0], - 'buildConfigurationList': [0, XCConfigurationList, 1, 1, - XCConfigurationList()], + 'buildConfigurationList': [0, XCConfigurationList, 1, 1, XCConfigurationList()], 'compatibilityVersion': [0, str, 0, 1, 'Xcode 3.2'], 'hasScannedForEncodings': [0, int, 0, 1, 1], 'mainGroup': [0, PBXGroup, 1, 1, PBXGroup()], @@ -2582,8 +2586,7 @@ class PBXProject(XCContainerPortal): def __init__(self, properties=None, id=None, parent=None, path=None): self.path = path self._other_pbxprojects = {} - # super - return XCContainerPortal.__init__(self, properties, id, parent) + super(PBXProject, self).__init__(properties, id, parent) def Name(self): name = self.path @@ -2676,14 +2679,14 @@ def RootGroupForPath(self, path): } (source_tree, path) = SourceTreeAndPathFromPath(path) - if source_tree != None and source_tree in source_tree_groups: + if source_tree is not None and source_tree in source_tree_groups: (group_func, hierarchical) = source_tree_groups[source_tree] group = group_func() - return (group, hierarchical) + return group, hierarchical # TODO(mark): make additional choices based on file extension. - return (self.SourceGroup(), True) + return self.SourceGroup(), True def AddOrGetFileInRootGroup(self, path): """Returns a PBXFileReference corresponding to path in the correct group @@ -2706,9 +2709,7 @@ def RootGroupsTakeOverOnlyChildren(self, recurse=False): def SortGroups(self): # Sort the children of the mainGroup (like "Source" and "Products") # according to their defined order. - self._properties['mainGroup']._properties['children'] = \ - sorted(self._properties['mainGroup']._properties['children'], - cmp=lambda x,y: x.CompareRootGroup(y)) + self._properties['mainGroup']._properties['children'].sort(key=cmp_to_key(XCHierarchicalElement.CompareRootGroup)) # Sort everything else by putting group before files, and going # alphabetically by name within sections of groups and files. SortGroup @@ -2755,9 +2756,6 @@ def AddOrGetProjectReference(self, other_pbxproject): if not 'projectReferences' in self._properties: self._properties['projectReferences'] = [] - product_group = None - project_ref = None - if not other_pbxproject in self._other_pbxprojects: # This project file isn't yet linked to the other one. Establish the # link. @@ -2911,7 +2909,7 @@ def CompareProducts(x, y, remote_products): # determine the sort order. return cmp(x_index, y_index) - for other_pbxproject, ref_dict in self._other_pbxprojects.iteritems(): + for other_pbxproject, ref_dict in self._other_pbxprojects.items(): # Build up a list of products in the remote project file, ordered the # same as the targets that produce them. remote_products = [] @@ -2956,8 +2954,7 @@ def Print(self, file=sys.stdout): self._XCPrint(file, 0, '{ ') else: self._XCPrint(file, 0, '{\n') - for property, value in sorted(self._properties.iteritems(), - cmp=lambda x, y: cmp(x, y)): + for property, value in sorted(self._properties.items()): if property == 'objects': self._PrintObjects(file) else: diff --git a/tools/gyp/pylib/gyp/input.py b/tools/gyp/gyp/input.py similarity index 75% rename from tools/gyp/pylib/gyp/input.py rename to tools/gyp/gyp/input.py index cdf33fd9469325..81246a6bd907fd 100644 --- a/tools/gyp/pylib/gyp/input.py +++ b/tools/gyp/gyp/input.py @@ -2,30 +2,24 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -from compiler.ast import Const -from compiler.ast import Dict -from compiler.ast import Discard -from compiler.ast import List -from compiler.ast import Module -from compiler.ast import Node -from compiler.ast import Stmt -import compiler -import gyp.common -import gyp.simple_copy -import multiprocessing -import optparse +from __future__ import print_function + +import ast import os.path import re import shlex -import signal import subprocess import sys -import threading -import time import traceback -from gyp.common import GypError -from gyp.common import OrderedSet +from collections import OrderedDict + +import gyp.common +import gyp.lib.simple_copy +from gyp.common import GypError, OrderedSet +if not 'unicode' in __builtins__: + unicode = str + basestring = str # A list of types that are treated as linkable. linkable_types = [ @@ -37,7 +31,7 @@ ] # A list of sections that contain links to other targets. -dependency_sections = ['dependencies', 'export_dependent_settings'] +dependency_sections = ['dependencies', 'export_dependent_settings', ] # base_path_sections is a list of sections defined by GYP that contain # pathnames. The generators can provide more keys, the two lists are merged @@ -59,6 +53,7 @@ per_process_data = {} per_process_aux_data = {} + def IsPathSection(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, @@ -83,6 +78,7 @@ def IsPathSection(section): 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 @@ -141,6 +137,7 @@ def IsPathSection(section): # } 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. @@ -183,50 +180,43 @@ def CheckedEval(file_contents): Note that this is slower than eval() is. """ - ast = compiler.parse(file_contents) - assert isinstance(ast, Module) - c1 = ast.getChildren() - assert c1[0] is None - assert isinstance(c1[1], Stmt) - c2 = c1[1].getChildren() - assert isinstance(c2[0], Discard) - c3 = c2[0].getChildren() - assert len(c3) == 1 - return CheckNode(c3[0], []) + syntax_tree = ast.parse(file_contents) + assert isinstance(syntax_tree, ast.Module) + c1 = syntax_tree.body + assert len(c1) == 1 + c2 = c1[0] + assert isinstance(c2, ast.Expr) + return CheckNode(c2.value, []) def CheckNode(node, keypath): - if isinstance(node, Dict): - c = node.getChildren() + if isinstance(node, ast.Dict): dict = {} - for n in range(0, len(c), 2): - assert isinstance(c[n], Const) - key = c[n].getChildren()[0] + for key, value in zip(node.keys, node.values): + assert isinstance(key, ast.Str) + key = key.s if key in dict: - raise GypError("Key '" + key + "' repeated at level " + - repr(len(keypath) + 1) + " with key path '" + - '.'.join(keypath) + "'") + raise GypError("Key '" + key + "' repeated at level " + repr(len(keypath) + 1) + " with key path '" + '.'.join(keypath) + "'") kp = list(keypath) # Make a copy of the list for descending this node. kp.append(key) - dict[key] = CheckNode(c[n + 1], kp) + dict[key] = CheckNode(value, kp) return dict - elif isinstance(node, List): - c = node.getChildren() + elif isinstance(node, ast.List): children = [] - for index, child in enumerate(c): + for index, child in enumerate(node.elts): kp = list(keypath) # Copy list. kp.append(repr(index)) children.append(CheckNode(child, kp)) return children - elif isinstance(node, Const): - return node.getChildren()[0] + elif isinstance(node, ast.Str): + return node.s + elif isinstance(node, ast.Num): + return node.n 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, includes, - is_target, check): +def LoadOneBuildFile(build_file_path, data, aux_data, includes): if build_file_path in data: return data[build_file_path] @@ -235,17 +225,12 @@ def LoadOneBuildFile(build_file_path, data, aux_data, includes, else: raise GypError("%s not found (cwd: %s)" % (build_file_path, os.getcwd())) - build_file_data = None try: - if check: - build_file_data = CheckedEval(build_file_contents) - else: - build_file_data = eval(build_file_contents, {'__builtins__': None}, - None) - except SyntaxError, e: + build_file_data = CheckedEval(build_file_contents) + except SyntaxError as e: e.filename = build_file_path raise - except Exception, e: + except Exception as e: gyp.common.ExceptionAppend(e, 'while reading ' + build_file_path) raise @@ -253,38 +238,29 @@ def LoadOneBuildFile(build_file_path, data, aux_data, includes, raise GypError("%s does not evaluate to a dictionary." % build_file_path) data[build_file_path] = build_file_data - aux_data[build_file_path] = {} + aux_data[build_file_path] = OrderedDict() # Scan for includes and merge them in. - if ('skip_includes' not in build_file_data or - not build_file_data['skip_includes']): + 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) + LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data, aux_data, includes) + except Exception as 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, - includes, check): +def LoadBuildFileIncludesIntoDict(subdict, subdict_path, data, aux_data, includes=None): includes_list = [] - if includes != None: + if includes is not None: includes_list.extend(includes) if 'includes' in subdict: for include in subdict['includes']: # "include" is specified relative to subdict_path, so compute the real # path to include by appending the provided "include" to the directory # in which subdict_path resides. - relative_include = \ - os.path.normpath(os.path.join(os.path.dirname(subdict_path), include)) + relative_include = os.path.normpath(os.path.join(os.path.dirname(subdict_path), include)) includes_list.append(relative_include) # Unhook the includes list, it's no longer needed. del subdict['includes'] @@ -297,28 +273,24 @@ def LoadBuildFileIncludesIntoDict(subdict, subdict_path, data, aux_data, gyp.DebugOutput(gyp.DEBUG_INCLUDES, "Loading Included File: '%s'", include) - MergeDicts(subdict, - LoadOneBuildFile(include, data, aux_data, None, False, check), - subdict_path, include) + MergeDicts(subdict, LoadOneBuildFile(include, data, aux_data, None), subdict_path, include) # Recurse into subdictionaries. - for k, v in subdict.iteritems(): + for k, v in subdict.items(): if type(v) is dict: - LoadBuildFileIncludesIntoDict(v, subdict_path, data, aux_data, - None, check) + LoadBuildFileIncludesIntoDict(v, subdict_path, data, aux_data) elif type(v) is list: - LoadBuildFileIncludesIntoList(v, subdict_path, data, aux_data, - check) + LoadBuildFileIncludesIntoList(v, subdict_path, data, aux_data) # This recurses into lists so that it can look for dicts. -def LoadBuildFileIncludesIntoList(sublist, sublist_path, data, aux_data, check): +def LoadBuildFileIncludesIntoList(sublist, sublist_path, data, aux_data): for item in sublist: if type(item) is dict: - LoadBuildFileIncludesIntoDict(item, sublist_path, data, aux_data, - None, check) + LoadBuildFileIncludesIntoDict(item, sublist_path, data, aux_data) elif type(item) is list: - LoadBuildFileIncludesIntoList(item, sublist_path, data, aux_data, check) + LoadBuildFileIncludesIntoList(item, sublist_path, data, aux_data) + # Processes toolsets in all the targets. This recurses into condition entries # since they can contain toolsets as well. @@ -342,7 +314,7 @@ def ProcessToolsetsInDict(data): if len(toolsets) > 0: # Optimization: only do copies if more than one toolset is specified. for build in toolsets[1:]: - new_target = gyp.simple_copy.deepcopy(target) + new_target = gyp.lib.simple_copy.deepcopy(target) new_target['toolset'] = build new_target_list.append(new_target) target['toolset'] = toolsets[0] @@ -359,8 +331,7 @@ def ProcessToolsetsInDict(data): # TODO(mark): I don't love this name. It just means that it's going to load # a build file that contains targets and is expected to provide a targets dict # that contains the targets... -def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes, - depth, check, load_dependencies): +def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes, depth, load_dependencies): # If depth is set, predefine the DEPTH variable to be a relative path from # this build file's directory to the directory identified by depth. if depth: @@ -385,11 +356,9 @@ def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes, return False data['target_build_files'].add(build_file_path) - gyp.DebugOutput(gyp.DEBUG_INCLUDES, - "Loading Target Build File '%s'", 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, - includes, True, check) + build_file_data = LoadOneBuildFile(build_file_path, data, aux_data, includes) # Store DEPTH for later use in generators. build_file_data['_DEPTH'] = depth @@ -404,9 +373,7 @@ def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes, for included_file in included: # included_file is relative to the current directory, but it needs to # be made relative to build_file_path's directory. - included_relative = \ - gyp.common.RelativePath(included_file, - os.path.dirname(build_file_path)) + included_relative = gyp.common.RelativePath(included_file, os.path.dirname(build_file_path)) build_file_data['included_files'].append(included_relative) # Do a first round of toolsets expansion so that conditions can be defined @@ -414,8 +381,7 @@ def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes, ProcessToolsetsInDict(build_file_data) # Apply "pre"/"early" variable expansions and condition evaluations. - ProcessVariablesAndConditionsInDict( - build_file_data, PHASE_EARLY, variables, build_file_path) + ProcessVariablesAndConditionsInDict(build_file_data, PHASE_EARLY, variables, build_file_path) # Since some toolsets might have been defined conditionally, perform # a second round of toolsets expansion now. @@ -425,8 +391,7 @@ def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes, # targets. if 'target_defaults' in build_file_data: if 'targets' not in build_file_data: - raise GypError("Unable to find targets in build file %s" % - build_file_path) + raise GypError("Unable to find targets in build file %s" % build_file_path) index = 0 while index < len(build_file_data['targets']): @@ -438,10 +403,8 @@ def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes, # 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 = gyp.simple_copy.deepcopy( - build_file_data['target_defaults']) - MergeDicts(new_target_dict, old_target_dict, - build_file_path, build_file_path) + new_target_dict = gyp.lib.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 index += 1 @@ -459,172 +422,28 @@ def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes, if 'dependencies' not in target_dict: continue for dependency in target_dict['dependencies']: - dependencies.append( - gyp.common.ResolveTarget(build_file_path, dependency, None)[0]) + dependencies.append(gyp.common.ResolveTarget(build_file_path, dependency, None)[0]) if load_dependencies: for dependency in dependencies: try: - LoadTargetBuildFile(dependency, data, aux_data, variables, - includes, depth, check, load_dependencies) - except Exception, e: - gyp.common.ExceptionAppend( - e, 'while loading dependencies of %s' % build_file_path) + LoadTargetBuildFile(dependency, data, aux_data, variables, includes, depth, load_dependencies) + except Exception as e: + gyp.common.ExceptionAppend(e, 'while loading dependencies of %s' % build_file_path) raise else: return (build_file_path, dependencies) -def CallLoadTargetBuildFile(global_flags, - 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 - a worker process. - """ - - try: - signal.signal(signal.SIGINT, signal.SIG_IGN) - - # Apply globals so that the worker process behaves the same. - for key, value in global_flags.iteritems(): - globals()[key] = value - - 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 - - # 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, - 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, traceback.format_exc() - return None - - -class ParallelProcessingError(Exception): - pass - - -class ParallelState(object): - """Class to keep track of state when processing input files in parallel. - - If build files are loaded in parallel, use this to keep track of - state during farming out and processing parallel jobs. It's stored - in a global so that the callback function can have access to it. - """ - - def __init__(self): - # The multiprocessing pool. - self.pool = None - # The condition variable used to protect this object and notify - # the main loop when there might be more data to process. - self.condition = None - # The "data" dict that was passed to LoadTargetBuildFileParallel - self.data = None - # The number of parallel calls outstanding; decremented when a response - # was received. - self.pending = 0 - # The set of all build files that have been scheduled, so we don't - # schedule the same one twice. - self.scheduled = set() - # A list of dependency build file paths that haven't been scheduled yet. - self.dependencies = [] - # Flag to indicate if there was an error in a child process. - self.error = False - - def LoadTargetBuildFileCallback(self, result): - """Handle the results of running LoadTargetBuildFile in another process. - """ - self.condition.acquire() - if not result: - self.error = True - self.condition.notify() - self.condition.release() - return - (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 new_dependency in dependencies0: - if new_dependency not in self.scheduled: - self.scheduled.add(new_dependency) - self.dependencies.append(new_dependency) - self.pending -= 1 - self.condition.notify() - self.condition.release() - - -def LoadTargetBuildFilesParallel(build_files, data, variables, includes, depth, - check, generator_input_info): - parallel_state = ParallelState() - parallel_state.condition = threading.Condition() - # 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 - - try: - parallel_state.condition.acquire() - while parallel_state.dependencies or parallel_state.pending: - if parallel_state.error: - break - if not parallel_state.dependencies: - parallel_state.condition.wait() - continue - - dependency = parallel_state.dependencies.pop() - - parallel_state.pending += 1 - global_flags = { - 'path_sections': globals()['path_sections'], - 'non_configuration_keys': globals()['non_configuration_keys'], - 'multiple_toolsets': globals()['multiple_toolsets']} - - if not parallel_state.pool: - parallel_state.pool = multiprocessing.Pool(multiprocessing.cpu_count()) - parallel_state.pool.apply_async( - CallLoadTargetBuildFile, - args = (global_flags, dependency, - variables, includes, depth, check, generator_input_info), - callback = parallel_state.LoadTargetBuildFileCallback) - except KeyboardInterrupt, e: - parallel_state.pool.terminate() - raise e - - parallel_state.condition.release() - - 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 # the input is something like "<(foo <(bar)) blah", then it would # return (1, 13), indicating the entire string except for the leading # "<" and trailing " blah". -LBRACKETS= set('{[(') +LBRACKETS = set('{[(') BRACKETS = {'}': '{', ']': '[', ')': '('} + + def FindEnclosingBracketGroup(input_str): stack = [] start = -1 @@ -669,24 +488,24 @@ def IsStrCanonicalInt(string): # "(?P<(?:(?:!?@?)|\|)?)' - r'(?P[-a-zA-Z0-9_.]+)?' - r'\((?P\s*\[?)' - r'(?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( - r'(?P(?P>(?:(?:!?@?)|\|)?)' - r'(?P[-a-zA-Z0-9_.]+)?' - r'\((?P\s*\[?)' - r'(?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( - r'(?P(?P[\^](?:(?:!?@?)|\|)?)' - r'(?P[-a-zA-Z0-9_.]+)?' - r'\((?P\s*\[?)' - r'(?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. @@ -722,9 +541,6 @@ def ExpandVariables(input, phase, variables, build_file): assert False input_str = str(input) - if IsStrCanonicalInt(input_str): - return int(input_str) - # Do a quick scan to determine if an expensive regex search is warranted. if expansion_symbol not in input_str: return input_str @@ -760,7 +576,6 @@ def ExpandVariables(input, phase, variables, build_file): # Capture these now so we can adjust them later. replace_start = match_group.start('replace') - replace_end = match_group.end('replace') # Find the ending paren, and re-evaluate the contained string. (c_start, c_end) = FindEnclosingBracketGroup(input_str[replace_start:]) @@ -785,11 +600,10 @@ def ExpandVariables(input, phase, variables, build_file): # 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 = gyp.simple_copy.deepcopy(variables) + processed_variables = gyp.lib.simple_copy.deepcopy(variables) ProcessListFiltersInDict(contents, processed_variables) # Recurse to expand variables in the contents - contents = ExpandVariables(contents, phase, - processed_variables, build_file) + contents = ExpandVariables(contents, phase, processed_variables, build_file) else: # Recurse to expand variables in the contents contents = ExpandVariables(contents, phase, variables, build_file) @@ -806,6 +620,7 @@ def ExpandVariables(input, phase, variables, build_file): # expansion in the input string. expand_to_list = '@' in match['type'] and input_str == replacement + build_file_dir = None if run_command or file_list: # Find the build file's directory, so commands can be run or file lists # generated relative to it. @@ -866,38 +681,31 @@ def ExpandVariables(input, phase, variables, build_file): 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, - "Executing command '%s' in directory '%s'", - contents, build_file_dir) - - replacement = '' + gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Executing command '%s' in directory '%s'", contents, build_file_dir) if command_string == 'pymod_do_main': - # 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)) + 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) + 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): +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) + 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__) + 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: @@ -1092,15 +875,17 @@ def EvalSingleCondition( 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) + except SyntaxError as e: + traceback.print_exc(file=sys.stderr) + 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)) + except NameError as e: + traceback.print_exc(file=sys.stderr) + gyp.common.ExceptionAppend(e, 'while evaluating condition \'%s\' in %s\nvariables=%r' % (cond_expr_expanded, build_file, variables)) + raise GypError(e) + except TypeError as e: + traceback.print_exc(file=sys.stderr) + gyp.common.ExceptionAppend(e, 'while evaluating condition \'%s\' in %s' % (cond_expr_expanded, build_file)) raise GypError(e) @@ -1138,14 +923,12 @@ def ProcessConditionsInDict(the_dict, phase, variables, build_file): del the_dict[conditions_key] for condition in conditions_list: - merge_dict = EvalCondition(condition, conditions_key, phase, variables, - build_file) + merge_dict = EvalCondition(condition, conditions_key, phase, variables, build_file) - if merge_dict != None: - # Expand variables and nested conditinals in the merge_dict before + if merge_dict is not None: + # Expand variables and nested conditionals in the merge_dict before # merging it. - ProcessVariablesAndConditionsInDict(merge_dict, phase, - variables, build_file) + ProcessVariablesAndConditionsInDict(merge_dict, phase, variables, build_file) MergeDicts(the_dict, merge_dict, build_file, build_file) @@ -1153,7 +936,7 @@ def ProcessConditionsInDict(the_dict, phase, variables, build_file): def LoadAutomaticVariablesFromDict(variables, the_dict): # 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(): + for key, value in the_dict.items(): if type(value) in (str, int, list): variables['_' + key] = value @@ -1166,7 +949,7 @@ def LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key): # the_dict in the_dict's parent dict. If the_dict's parent is not a dict # (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(): + for key, value in the_dict.get('variables', {}).items(): if type(value) not in (str, int, list): continue @@ -1186,8 +969,7 @@ def LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key): variables[variable_name] = value -def ProcessVariablesAndConditionsInDict(the_dict, phase, variables_in, - build_file, the_dict_key=None): +def ProcessVariablesAndConditionsInDict(the_dict, phase, variables_in, build_file, the_dict_key=None): """Handle all variable and command expansion and conditional evaluation. This function is the public entry point for all variable expansions and @@ -1205,7 +987,7 @@ def ProcessVariablesAndConditionsInDict(the_dict, phase, variables_in, # list before we process them so that you can reference one # variable from another. They will be fully expanded by recursion # in ExpandVariables. - for key, value in the_dict['variables'].iteritems(): + for key, value in the_dict['variables'].items(): variables[key] = value # Handle the associated variables dict first, so that any variable @@ -1213,19 +995,16 @@ def ProcessVariablesAndConditionsInDict(the_dict, phase, variables_in, # Pass a copy of the variables dict to avoid having it be tainted. # Otherwise, it would have extra automatics added for everything that # should just be an ordinary variable in this scope. - ProcessVariablesAndConditionsInDict(the_dict['variables'], phase, - variables, build_file, 'variables') + ProcessVariablesAndConditionsInDict(the_dict['variables'], phase, variables, build_file, 'variables') LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key) - for key, value in the_dict.iteritems(): + for key, value in the_dict.items(): # Skip "variables", which was already processed if present. if key != 'variables' and type(value) is str: expanded = ExpandVariables(value, phase, variables, build_file) 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) + raise ValueError('Variable expansion in this context permits str and int only, found ' + expanded.__class__.__name__ + ' for ' + key) the_dict[key] = expanded # Variable expansion may have resulted in changes to automatics. Reload. @@ -1276,7 +1055,7 @@ def ProcessVariablesAndConditionsInDict(the_dict, phase, variables_in, # Recurse into child dicts, or process child lists which may result in # further recursion into descendant dicts. - for key, value in the_dict.iteritems(): + for key, value in the_dict.items(): # Skip "variables" and string values, which were already processed if # present. if key == 'variables' or type(value) is str: @@ -1284,22 +1063,18 @@ def ProcessVariablesAndConditionsInDict(the_dict, phase, variables_in, 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) + ProcessVariablesAndConditionsInDict(value, phase, variables, build_file, key) 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) + ProcessVariablesAndConditionsInList(value, phase, variables, build_file) elif type(value) is not int: - raise TypeError('Unknown type ' + value.__class__.__name__ + \ - ' for ' + key) + raise TypeError('Unknown type ' + value.__class__.__name__ + ' for ' + key) -def ProcessVariablesAndConditionsInList(the_list, phase, variables, - build_file): +def ProcessVariablesAndConditionsInList(the_list, phase, variables, build_file): # Iterate using an index so that new values can be assigned into the_list. index = 0 while index < len(the_list): @@ -1315,20 +1090,16 @@ def ProcessVariablesAndConditionsInList(the_list, phase, variables, if type(expanded) in (str, int): the_list[index] = expanded elif type(expanded) is list: - the_list[index:index+1] = expanded + the_list[index:index + 1] = expanded index += len(expanded) # index now identifies the next item to examine. Continue right now # without falling into the index increment below. continue else: - raise ValueError( - 'Variable expansion in this context permits strings and ' + \ - 'lists only, found ' + expanded.__class__.__name__ + ' at ' + \ - index) + raise ValueError('Variable expansion in this context permits strings and lists only, found ' + expanded.__class__.__name__ + ' at ' + index) elif type(item) is not int: - raise TypeError('Unknown type ' + item.__class__.__name__ + \ - ' at index ' + index) + raise TypeError('Unknown type ' + item.__class__.__name__ + ' at index ' + index) index = index + 1 @@ -1344,13 +1115,10 @@ def BuildTargetsDict(data): in the returned dict. These keys provide access to the target dicts, the dicts in the "targets" lists. """ - - targets = {} + targets = OrderedDict() for build_file in data['target_build_files']: for target in data[build_file].get('targets', []): - target_name = gyp.common.QualifiedTarget(build_file, - target['target_name'], - target['toolset']) + target_name = gyp.common.QualifiedTarget(build_file, target['target_name'], target['toolset']) if target_name in targets: raise GypError('Duplicate target definitions for ' + target_name) targets[target_name] = target @@ -1369,32 +1137,25 @@ def QualifyDependencies(targets): similar dict. """ - all_dependency_sections = [dep + op - for dep in dependency_sections - for op in ('', '!', '/')] + all_dependency_sections = [dep + op for dep in dependency_sections for op in ('', '!', '/')] - for target, target_dict in targets.iteritems(): + for target, target_dict in targets.items(): target_build_file = gyp.common.BuildFile(target) toolset = target_dict['toolset'] for dependency_key in all_dependency_sections: dependencies = target_dict.get(dependency_key, []) - for index in xrange(0, len(dependencies)): - dep_file, dep_target, dep_toolset = gyp.common.ResolveTarget( - target_build_file, dependencies[index], toolset) + for index, dep in enumerate(dependencies): + dep_file, dep_target, dep_toolset = gyp.common.ResolveTarget(target_build_file, dep, toolset) if not multiple_toolsets: # Ignore toolset specification in the dependency if it is specified. dep_toolset = toolset - dependency = gyp.common.QualifiedTarget(dep_file, - dep_target, - dep_toolset) + dependency = gyp.common.QualifiedTarget(dep_file, dep_target, dep_toolset) dependencies[index] = dependency # Make sure anything appearing in a list other than "dependencies" also # appears in the "dependencies" list. - if dependency_key != 'dependencies' and \ - dependency not in target_dict['dependencies']: - raise GypError('Found ' + dependency + ' in ' + dependency_key + - ' of ' + target + ', but not in dependencies') + if dependency_key != 'dependencies' and dependency not in target_dict['dependencies']: + raise GypError('Found ' + dependency + ' in ' + dependency_key + ' of ' + target + ', but not in dependencies') def ExpandWildcardDependencies(targets, data): @@ -1413,8 +1174,7 @@ def ExpandWildcardDependencies(targets, data): dependency list, must be qualified when this function is called. """ - for target, target_dict in targets.iteritems(): - toolset = target_dict['toolset'] + for target, target_dict in targets.items(): target_build_file = gyp.common.BuildFile(target) for dependency_key in dependency_sections: dependencies = target_dict.get(dependency_key, []) @@ -1423,8 +1183,7 @@ def ExpandWildcardDependencies(targets, data): # because the dependencies list will be modified within the loop body. index = 0 while index < len(dependencies): - (dependency_build_file, dependency_target, dependency_toolset) = \ - gyp.common.ParseQualifiedTarget(dependencies[index]) + (dependency_build_file, dependency_target, dependency_toolset) = gyp.common.ParseQualifiedTarget(dependencies[index]) if dependency_target != '*' and dependency_toolset != '*': # Not a wildcard. Keep it moving. index = index + 1 @@ -1433,8 +1192,7 @@ def ExpandWildcardDependencies(targets, data): if dependency_build_file == target_build_file: # It's an error for a target to depend on all other targets in # the same file, because a target cannot depend on itself. - raise GypError('Found wildcard in ' + dependency_key + ' of ' + - target + ' referring to same build file') + raise GypError('Found wildcard in ' + dependency_key + ' of ' + target + ' referring to same build file') # Take the wildcard out and adjust the index so that the next # dependency in the list will be processed the next time through the @@ -1450,16 +1208,12 @@ def ExpandWildcardDependencies(targets, data): if int(dependency_target_dict.get('suppress_wildcard', False)): continue dependency_target_name = dependency_target_dict['target_name'] - if (dependency_target != '*' and - dependency_target != dependency_target_name): + if (dependency_target != '*' and dependency_target != dependency_target_name): continue dependency_target_toolset = dependency_target_dict['toolset'] - if (dependency_toolset != '*' and - dependency_toolset != dependency_target_toolset): + if (dependency_toolset != '*' and dependency_toolset != dependency_target_toolset): continue - dependency = gyp.common.QualifiedTarget(dependency_build_file, - dependency_target_name, - dependency_target_toolset) + dependency = gyp.common.QualifiedTarget(dependency_build_file, dependency_target_name, dependency_target_toolset) index = index + 1 dependencies.insert(index, dependency) @@ -1475,7 +1229,7 @@ def Unify(l): def RemoveDuplicateDependencies(targets): """Makes sure every dependency appears only once in all targets's dependency lists.""" - for target_name, target_dict in targets.iteritems(): + for target_name, target_dict in targets.items(): for dependency_key in dependency_sections: dependencies = target_dict.get(dependency_key, []) if dependencies: @@ -1491,7 +1245,7 @@ def Filter(l, item): def RemoveSelfDependencies(targets): """Remove self dependencies from targets that have the prune_self_dependency variable set.""" - for target_name, target_dict in targets.iteritems(): + for target_name, target_dict in targets.items(): for dependency_key in dependency_sections: dependencies = target_dict.get(dependency_key, []) if dependencies: @@ -1504,15 +1258,14 @@ def RemoveSelfDependencies(targets): def RemoveLinkDependenciesFromNoneTargets(targets): """Remove dependencies having the 'link_dependency' attribute from the 'none' targets.""" - for target_name, target_dict in targets.iteritems(): + for target_name, target_dict in targets.items(): 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) + target_dict[dependency_key] = Filter(target_dict[dependency_key], t) class DependencyGraphNode(object): @@ -1535,22 +1288,21 @@ def __init__(self, ref): def __repr__(self): return '' % self.ref - def FlattenToList(self): + def __lt__(self, other): + return self.ref < other.ref + + def FlattenToList_NoCycles(self, nodes): # flat_list is the sorted list of dependencies - actually, the list items # 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 = OrderedSet() - def ExtractNodeRef(node): - """Extracts the object that the node represents from the given node.""" - return node.ref - # in_degree_zeros is the list of DependencyGraphNodes that have no # dependencies not in flat_list. Initially, it is a copy of the children # of this node, because when the graph was built, nodes with no # dependencies were made implicit dependents of the root node. - in_degree_zeros = sorted(self.dependents[:], key=ExtractNodeRef) + in_degree_zeros = sorted(self.dependents[:]) while in_degree_zeros: # Nodes in in_degree_zeros have no dependencies not in flat_list, so they @@ -1562,13 +1314,12 @@ def ExtractNodeRef(node): # 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 sorted(node.dependents, key=ExtractNodeRef): + for node_dependent in sorted(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 (sorted(node_dependent.dependencies, - key=ExtractNodeRef)): + for node_dependent_dependency in sorted(node_dependent.dependencies): if not node_dependent_dependency.ref in flat_list: # The dependent one or more dependencies not in flat_list. There # will be more chances to add it to flat_list when examining @@ -1583,6 +1334,21 @@ def ExtractNodeRef(node): # iteration of the outer loop. in_degree_zeros += [node_dependent] + if len(flat_list) != len(nodes) and len(nodes) != 0: + # If there's anything left unvisited, there must be a circular dependency (cycle). + if not self.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. + first_node = nodes.popitem()[1] + first_node.dependencies.append(self) + self.dependents.append(first_node) + + cycles = [] + for cycle in self.FindCycles(): + paths = [n.ref for n in cycle] + cycles.append('Cycle: %s' % ' -> '.join(paths)) + raise DependencyGraphNode.CircularException('Cycles in dependency graph detected:\n' + '\n'.join(cycles)) + return list(flat_list) def FindCycles(self): @@ -1590,7 +1356,7 @@ def FindCycles(self): Returns a list of cycles in the graph, where each cycle is its own list. """ results = [] - visited = set() + visited = OrderedSet() def Visit(node, path): for child in node.dependents: @@ -1649,8 +1415,7 @@ def _AddImportedDependencies(self, targets, dependencies=None): # dependency that exported them. This is done to more closely match # the depth-first method used by DeepDependencies. add_index = 1 - for imported_dependency in \ - dependency_dict.get('export_dependent_settings', []): + for imported_dependency in dependency_dict.get('export_dependent_settings', []): if imported_dependency not in dependencies: dependencies.insert(index + add_index, imported_dependency) add_index = add_index + 1 @@ -1684,8 +1449,7 @@ def DeepDependencies(self, dependencies=None): return dependencies - def _LinkDependenciesInternal(self, targets, include_shared_libraries, - dependencies=None, initial=True): + def _LinkDependenciesInternal(self, targets, include_shared_libraries, dependencies=None, initial=True): """Returns an OrderedSet of dependency targets that are linked into this target. @@ -1717,8 +1481,7 @@ def _LinkDependenciesInternal(self, targets, include_shared_libraries, raise GypError("Missing 'target_name' field in target.") if 'type' not in targets[self.ref]: - raise GypError("Missing 'type' field in target %s" % - targets[self.ref]['target_name']) + raise GypError("Missing 'type' field in target %s" % targets[self.ref]['target_name']) target_type = targets[self.ref]['type'] @@ -1732,8 +1495,7 @@ def _LinkDependenciesInternal(self, targets, include_shared_libraries, return dependencies # Don't traverse 'none' targets if explicitly excluded. - if (target_type == 'none' and - not targets[self.ref].get('dependencies_traverse', True)): + if (target_type == 'none' and not targets[self.ref].get('dependencies_traverse', True)): dependencies.add(self.ref) return dependencies @@ -1741,9 +1503,7 @@ def _LinkDependenciesInternal(self, targets, include_shared_libraries, # are already fully and finally linked. Nothing else can be a link # dependency of them, there can only be dependencies in the sense that a # dependent target might run an executable or load the loadable_module. - if not initial and target_type in ('executable', 'loadable_module', - 'mac_kernel_extension', - 'windows_driver'): + if not initial and target_type in ('executable', 'loadable_module', 'mac_kernel_extension', 'windows_driver'): return dependencies # Shared libraries are already fully linked. They should only be included @@ -1752,8 +1512,7 @@ def _LinkDependenciesInternal(self, targets, include_shared_libraries, # in |dependencies| when propagating link_settings. # The |include_shared_libraries| flag controls which of these two cases we # are handling. - if (not initial and target_type == 'shared_library' and - not include_shared_libraries): + if (not initial and target_type == 'shared_library' and not include_shared_libraries): return dependencies # The target is linkable, add it to the list of link dependencies. @@ -1765,9 +1524,7 @@ def _LinkDependenciesInternal(self, targets, include_shared_libraries, # this target linkable. Always look at dependencies of the initial # target, and always look at dependencies of non-linkables. for dependency in self.dependencies: - dependency._LinkDependenciesInternal(targets, - include_shared_libraries, - dependencies, False) + dependency._LinkDependenciesInternal(targets, include_shared_libraries, dependencies, False) return dependencies @@ -1781,8 +1538,7 @@ def DependenciesForLinkSettings(self, targets): # link_settings are propagated. So for now, we will allow it, unless the # 'allow_sharedlib_linksettings_propagation' flag is explicitly set to # False. Once chrome is fixed, we can remove this flag. - include_shared_libraries = \ - targets[self.ref].get('allow_sharedlib_linksettings_propagation', True) + include_shared_libraries = targets[self.ref].get('allow_sharedlib_linksettings_propagation', True) return self._LinkDependenciesInternal(targets, include_shared_libraries) def DependenciesToLinkAgainst(self, targets): @@ -1795,17 +1551,15 @@ def DependenciesToLinkAgainst(self, targets): def BuildDependencyList(targets): # Create a DependencyGraphNode for each target. Put it into a dict for easy # access. - dependency_nodes = {} - for target, spec in targets.iteritems(): + dependency_nodes = OrderedDict() + for target in targets.keys(): if target not in dependency_nodes: dependency_nodes[target] = DependencyGraphNode(target) - # Set up the dependency links. Targets that have no dependencies are treated - # as dependent on root_node. + # Set up the dependency links. Targets that have no dependencies are treated as dependent on root_node. root_node = DependencyGraphNode(None) - for target, spec in targets.iteritems(): + for target, spec in targets.items(): target_node = dependency_nodes[target] - target_build_file = gyp.common.BuildFile(target) dependencies = spec.get('dependencies') if not dependencies: target_node.dependencies = [root_node] @@ -1814,54 +1568,33 @@ def BuildDependencyList(targets): for dependency in dependencies: dependency_node = dependency_nodes.get(dependency) if not dependency_node: - raise GypError("Dependency '%s' not found while " - "trying to load target %s" % (dependency, target)) + raise GypError("Dependency '%s' not found while trying to load target %s" % (dependency, target)) target_node.dependencies.append(dependency_node) dependency_node.dependents.append(target_node) - flat_list = root_node.FlattenToList() - - # If there's anything left unvisited, there must be a circular dependency - # (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( - 'Cycles in dependency graph detected:\n' + '\n'.join(cycles)) - - return [dependency_nodes, flat_list] + flat_list = root_node.FlattenToList_NoCycles(dependency_nodes) + return [dict(dependency_nodes), flat_list] def VerifyNoGYPFileCircularDependencies(targets): # Create a DependencyGraphNode for each gyp file containing a target. Put # it into a dict for easy access. - dependency_nodes = {} - for target in targets.iterkeys(): + dependency_nodes = OrderedDict() + for target in targets.keys(): build_file = gyp.common.BuildFile(target) if not build_file in dependency_nodes: dependency_nodes[build_file] = DependencyGraphNode(build_file) # Set up the dependency links. - for target, spec in targets.iteritems(): + for target, spec in targets.items(): build_file = gyp.common.BuildFile(target) build_file_node = dependency_nodes[build_file] target_dependencies = spec.get('dependencies', []) for dependency in target_dependencies: try: dependency_build_file = gyp.common.BuildFile(dependency) - except GypError, e: - gyp.common.ExceptionAppend( - e, 'while computing dependencies of .gyp file %s' % build_file) + except GypError as e: + gyp.common.ExceptionAppend(e, 'while computing dependencies of .gyp file %s' % build_file) raise if dependency_build_file == build_file: @@ -1874,31 +1607,14 @@ def VerifyNoGYPFileCircularDependencies(targets): build_file_node.dependencies.append(dependency_node) dependency_node.dependents.append(build_file_node) - # Files that have no dependencies are treated as dependent on root_node. root_node = DependencyGraphNode(None) - for build_file_node in dependency_nodes.itervalues(): + for build_file_node in dependency_nodes.values(): if len(build_file_node.dependencies) == 0: build_file_node.dependencies.append(root_node) root_node.dependents.append(build_file_node) - flat_list = root_node.FlattenToList() - - # If there's anything left unvisited, there must be a circular dependency - # (cycle). - if len(flat_list) != len(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(): - 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)) + root_node.FlattenToList_NoCycles(dependency_nodes) def DoDependentSettings(key, flat_list, targets, dependency_nodes): @@ -1912,26 +1628,21 @@ def DoDependentSettings(key, flat_list, targets, dependency_nodes): if key == 'all_dependent_settings': dependencies = dependency_nodes[target].DeepDependencies() elif key == 'direct_dependent_settings': - dependencies = \ - dependency_nodes[target].DirectAndImportedDependencies(targets) + dependencies = dependency_nodes[target].DirectAndImportedDependencies(targets) elif key == 'link_settings': - dependencies = \ - dependency_nodes[target].DependenciesForLinkSettings(targets) + dependencies = dependency_nodes[target].DependenciesForLinkSettings(targets) else: - raise GypError("DoDependentSettings doesn't know how to determine " - 'dependencies for ' + key) + raise GypError("DoDependentSettings doesn't know how to determine dependencies for " + key) for dependency in dependencies: dependency_dict = targets[dependency] if not key in dependency_dict: continue dependency_build_file = gyp.common.BuildFile(dependency) - MergeDicts(target_dict, dependency_dict[key], - build_file, dependency_build_file) + MergeDicts(target_dict, dependency_dict[key], build_file, dependency_build_file) -def AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes, - sort_dependencies): +def AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes, sort_dependencies): # Recompute target "dependencies" properties. For each static library # target, remove "dependencies" entries referring to other static libraries, # unless the dependency has the "hard_dependency" attribute set. For each @@ -1946,8 +1657,7 @@ def AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes, if not 'dependencies' in target_dict: continue - target_dict['dependencies_original'] = target_dict.get( - 'dependencies', [])[:] + target_dict['dependencies_original'] = target_dict.get('dependencies', [])[:] # A static library should not depend on another static library unless # the dependency relationship is "hard," which should only be done when @@ -1957,8 +1667,7 @@ def AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes, # the non-hard dependency can safely be removed, but the exported hard # dependency must be added to the target to keep the same dependency # ordering. - dependencies = \ - dependency_nodes[target].DirectAndImportedDependencies(targets) + dependencies = dependency_nodes[target].DirectAndImportedDependencies(targets) index = 0 while index < len(dependencies): dependency = dependencies[index] @@ -1966,10 +1675,10 @@ def AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes, # Remove every non-hard static library dependency and remove every # non-static library dependency that isn't a direct dependency. - if (dependency_dict['type'] == 'static_library' and \ + if (dependency_dict['type'] == 'static_library' and not dependency_dict.get('hard_dependency', False)) or \ - (dependency_dict['type'] != 'static_library' and \ - not dependency in target_dict['dependencies']): + (dependency_dict['type'] != 'static_library' and + not dependency in target_dict['dependencies']): # Take the dependency out of the list, and don't increment index # because the next dependency to analyze will shift into the index # formerly occupied by the one being removed. @@ -1989,8 +1698,7 @@ def AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes, # target. Add them to the dependencies list if they're not already # present. - link_dependencies = \ - dependency_nodes[target].DependenciesToLinkAgainst(targets) + link_dependencies = dependency_nodes[target].DependenciesToLinkAgainst(targets) for dependency in link_dependencies: if dependency == target: continue @@ -2003,8 +1711,7 @@ def AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes, # Note: flat_list is already sorted in the order from dependencies to # dependents. if sort_dependencies and 'dependencies' in target_dict: - target_dict['dependencies'] = [dep for dep in reversed(flat_list) - if dep in target_dict['dependencies']] + target_dict['dependencies'] = [dep for dep in reversed(flat_list) if dep in target_dict['dependencies']] # Initialize this here to speed up MakePathRelative. @@ -2035,14 +1742,12 @@ def MakePathRelative(to_file, fro_file, item): # TODO(dglazkov) The backslash/forward-slash replacement at the end is a # temporary measure. This should really be addressed by keeping all paths # in POSIX until actual project generation. - ret = os.path.normpath(os.path.join( - gyp.common.RelativePath(os.path.dirname(fro_file), - os.path.dirname(to_file)), - item)).replace('\\', '/') + ret = os.path.normpath(os.path.join(gyp.common.RelativePath(os.path.dirname(fro_file), os.path.dirname(to_file)), item)).replace('\\', '/') if item[-1] == '/': ret += '/' return ret + def MergeLists(to, fro, to_file, fro_file, is_paths=False, append=True): # Python documentation recommends objects which do not support hash # set this value to None. Python library objects follow this rule. @@ -2088,9 +1793,7 @@ def is_in_set_or_list(x, s, l): to_item = [] MergeLists(to_item, item, to_file, fro_file) else: - raise TypeError( - 'Attempt to merge list item of unsupported type ' + \ - item.__class__.__name__) + raise TypeError('Attempt to merge list item of unsupported type ' + item.__class__.__name__) if append: # If appending a singleton that's already in the list, don't append. @@ -2117,7 +1820,7 @@ def is_in_set_or_list(x, s, l): def MergeDicts(to, fro, to_file, fro_file): # I wanted to name the parameter "from" but it's a Python keyword... - for k, v in fro.iteritems(): + for k, v in fro.items(): # It would be nice to do "if not k in to: to[k] = v" but that wouldn't give # copy semantics. Something else may want to merge from the |fro| dict # later, and having the same dict ref pointed to twice in the tree isn't @@ -2132,10 +1835,7 @@ def MergeDicts(to, fro, to_file, fro_file): bad_merge = True if bad_merge: - raise TypeError( - 'Attempt to merge dict value of type ' + v.__class__.__name__ + \ - ' into incompatible type ' + to[k].__class__.__name__ + \ - ' for key ' + k) + raise TypeError('Attempt to merge dict value of type ' + v.__class__.__name__ + ' into incompatible type ' + to[k].__class__.__name__ + ' for key ' + k) if type(v) in (str, int): # Overwrite the existing value, if any. Cheap and easy. is_path = IsPathSection(k) @@ -2183,8 +1883,7 @@ def MergeDicts(to, fro, to_file, fro_file): # and prepend are the only policies that can coexist. for list_incompatible in lists_incompatible: if list_incompatible in fro: - raise GypError('Incompatible list policies ' + k + ' and ' + - list_incompatible) + raise GypError('Incompatible list policies ' + k + ' and ' + list_incompatible) if list_base in to: if ext == '?': @@ -2194,10 +1893,7 @@ def MergeDicts(to, fro, to_file, fro_file): 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( - 'Attempt to merge dict value of type ' + v.__class__.__name__ + \ - ' into incompatible type ' + to[list_base].__class__.__name__ + \ - ' for key ' + list_base + '(' + k + ')') + 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 + ')') else: to[list_base] = [] @@ -2209,13 +1905,10 @@ def MergeDicts(to, fro, to_file, fro_file): is_paths = IsPathSection(list_base) MergeLists(to[list_base], v, to_file, fro_file, is_paths, append) else: - raise TypeError( - 'Attempt to merge dict value of unsupported type ' + \ - v.__class__.__name__ + ' for key ' + k) + raise TypeError('Attempt to merge dict value of unsupported type ' + v.__class__.__name__ + ' for key ' + k) -def MergeConfigWithInheritance(new_configuration_dict, build_file, - target_dict, configuration, visited): +def MergeConfigWithInheritance(new_configuration_dict, build_file, target_dict, configuration, visited): # Skip if previously visted. if configuration in visited: return @@ -2225,12 +1918,10 @@ def MergeConfigWithInheritance(new_configuration_dict, build_file, # Merge in parents. for parent in configuration_dict.get('inherit_from', []): - MergeConfigWithInheritance(new_configuration_dict, build_file, - target_dict, parent, visited + [configuration]) + MergeConfigWithInheritance(new_configuration_dict, build_file, target_dict, parent, visited + [configuration]) # Merge it into the new config. - MergeDicts(new_configuration_dict, configuration_dict, - build_file, build_file) + MergeDicts(new_configuration_dict, configuration_dict, build_file, build_file) # Drop abstract. if 'abstract' in new_configuration_dict: @@ -2252,13 +1943,12 @@ def SetUpConfigurations(target, target_dict): if not 'configurations' in target_dict: target_dict['configurations'] = {'Default': {}} if not 'default_configuration' in target_dict: - concrete = [i for (i, config) in target_dict['configurations'].iteritems() - if not config.get('abstract')] + concrete = [i for (i, config) in target_dict['configurations'].items() if not config.get('abstract')] target_dict['default_configuration'] = sorted(concrete)[0] merged_configurations = {} configs = target_dict['configurations'] - for (configuration, old_configuration_dict) in configs.iteritems(): + for (configuration, old_configuration_dict) in configs.items(): # Skip abstract configurations (saves work only). if old_configuration_dict.get('abstract'): continue @@ -2266,31 +1956,27 @@ def SetUpConfigurations(target, target_dict): # Get the inheritance relationship right by making a copy of the target # dict. new_configuration_dict = {} - for (key, target_val) in target_dict.iteritems(): + for (key, target_val) in target_dict.items(): key_ext = key[-1:] if key_ext in key_suffixes: key_base = key[:-1] else: key_base = key if not key_base in non_configuration_keys: - new_configuration_dict[key] = gyp.simple_copy.deepcopy(target_val) + new_configuration_dict[key] = gyp.lib.simple_copy.deepcopy(target_val) # Merge in configuration (with all its parents first). - MergeConfigWithInheritance(new_configuration_dict, build_file, - target_dict, configuration, []) + MergeConfigWithInheritance(new_configuration_dict, build_file, target_dict, configuration, []) 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]) + target_dict['configurations'][configuration] = merged_configurations[configuration] # Now drop all the abstract ones. - for configuration in target_dict['configurations'].keys(): - old_configuration_dict = target_dict['configurations'][configuration] - if old_configuration_dict.get('abstract'): - del target_dict['configurations'][configuration] + configs = target_dict['configurations'] + target_dict['configurations'] = {k: v for k, v in configs.items() if not v.get('abstract')} # Now that all of the target's configurations have been built, go through # the target dict's keys and remove everything that's been moved into a @@ -2312,9 +1998,7 @@ def SetUpConfigurations(target, target_dict): configuration_dict = target_dict['configurations'][configuration] for key in configuration_dict.keys(): if key in invalid_configuration_keys: - raise GypError('%s not allowed in the %s configuration, found in ' - 'target %s' % (key, configuration, target)) - + raise GypError('%s not allowed in the %s configuration, found in target %s' % (key, configuration, target)) def ProcessListFiltersInDict(name, the_dict): @@ -2350,14 +2034,13 @@ def ProcessListFiltersInDict(name, the_dict): lists = [] del_lists = [] - for key, value in the_dict.iteritems(): + for key, value in the_dict.items(): operation = key[-1] if operation != '!' and operation != '/': continue if type(value) is not list: - raise ValueError(name + ' key ' + key + ' must be list, not ' + \ - value.__class__.__name__) + raise ValueError(name + ' key ' + key + ' must be list, not ' + value.__class__.__name__) list_key = key[:-1] if list_key not in the_dict: @@ -2369,10 +2052,7 @@ def ProcessListFiltersInDict(name, the_dict): 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]) + 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) @@ -2398,8 +2078,8 @@ def ProcessListFiltersInDict(name, the_dict): exclude_key = list_key + '!' if exclude_key in the_dict: for exclude_item in the_dict[exclude_key]: - for index in xrange(0, len(the_list)): - if exclude_item == the_list[index]: + for index, list_item in enumerate(the_list): + if exclude_item == list_item: # This item matches the exclude_item, so set its action to 0 # (exclude). list_actions[index] = 0 @@ -2421,11 +2101,9 @@ def ProcessListFiltersInDict(name, the_dict): 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] + for index, list_item in enumerate(the_list): if list_actions[index] == action_value: # Even if the regex matches, nothing will change so continue (regex # searches are expensive). @@ -2445,9 +2123,7 @@ def ProcessListFiltersInDict(name, the_dict): # to be created. excluded_key = list_key + '_excluded' if excluded_key in the_dict: - raise GypError(name + ' key ' + excluded_key + - ' must not be present prior ' - ' to applying exclusion/regex filters for ' + list_key) + raise GypError(name + ' key ' + excluded_key + ' must not be present prior to applying exclusion/regex filters for ' + list_key) excluded_list = [] @@ -2455,7 +2131,7 @@ def ProcessListFiltersInDict(name, the_dict): # the indices of items that haven't been seen yet don't shift. That means # that things need to be prepended to excluded_list to maintain them in the # same order that they existed in the_list. - for index in xrange(len(list_actions) - 1, -1, -1): + for index in range(len(list_actions) - 1, -1, -1): if list_actions[index] == 0: # Dump anything with action 0 (exclude). Keep anything with action 1 # (include) or -1 (no include or exclude seen for the item). @@ -2468,7 +2144,7 @@ def ProcessListFiltersInDict(name, the_dict): the_dict[excluded_key] = excluded_list # Now recurse into subdicts and lists that may contain dicts. - for key, value in the_dict.iteritems(): + for key, value in the_dict.items(): if type(value) is dict: ProcessListFiltersInDict(key, value) elif type(value) is list: @@ -2492,47 +2168,34 @@ def ValidateTargetType(target, target_dict): Raises an exception on error. """ - VALID_TARGET_TYPES = ('executable', 'loadable_module', - 'static_library', 'shared_library', - 'mac_kernel_extension', 'none', 'windows_driver') + VALID_TARGET_TYPES = ('executable', 'loadable_module', 'static_library', 'shared_library', 'mac_kernel_extension', 'none', 'windows_driver') target_type = target_dict.get('type', None) if target_type not in VALID_TARGET_TYPES: - raise GypError("Target %s has an invalid target type '%s'. " - "Must be one of %s." % - (target, target_type, '/'.join(VALID_TARGET_TYPES))) - if (target_dict.get('standalone_static_library', 0) and - not target_type == 'static_library'): - raise GypError('Target %s has type %s but standalone_static_library flag is' - ' only valid for static_library type.' % (target, - target_type)) - - -def ValidateSourcesInTarget(target, target_dict, build_file, - duplicate_basename_check): - if not duplicate_basename_check: - return + raise GypError("Target %s has an invalid target type '%s'. Must be one of %s." % (target, target_type, '/'.join(VALID_TARGET_TYPES))) + if (target_dict.get('standalone_static_library', 0) and not target_type == 'static_library'): + raise GypError('Target %s has type %s but standalone_static_library flag is only valid for static_library type.' % (target, target_type)) + + +def ValidateSourcesInTarget(target, target_dict): if target_dict.get('type', None) != 'static_library': return sources = target_dict.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'] + 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(): + for basename, files in basenames.items(): 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' % - target + error + 'libtool on Mac cannot handle that. Use ' - '--no-duplicate-basename-check to disable this validation.') + print('static library %s has several files with the same basename:\n' % 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') @@ -2557,31 +2220,24 @@ def ValidateRulesInTarget(target, target_dict, extra_sources_for_rules): # Make sure that there's no conflict among rule names and extensions. rule_name = rule['rule_name'] if rule_name in rule_names: - raise GypError('rule %s exists in duplicate, target %s' % - (rule_name, target)) + raise GypError('rule %s exists in duplicate, target %s' % (rule_name, target)) rule_names[rule_name] = rule rule_extension = rule['extension'] if rule_extension.startswith('.'): rule_extension = rule_extension[1:] if rule_extension in rule_extensions: - raise GypError(('extension %s associated with multiple rules, ' + - 'target %s rules %s and %s') % - (rule_extension, target, - rule_extensions[rule_extension]['rule_name'], - rule_name)) + raise GypError(('extension %s associated with multiple rules, ' + 'target %s rules %s and %s') % (rule_extension, target, rule_extensions[rule_extension]['rule_name'], rule_name)) rule_extensions[rule_extension] = rule # Make sure rule_sources isn't already there. It's going to be # created below if needed. if 'rule_sources' in rule: - raise GypError( - 'rule_sources must not exist in input, target %s rule %s' % - (target, rule_name)) + raise GypError('rule_sources must not exist in input, target %s rule %s' % (target, rule_name)) rule_sources = [] - source_keys = ['sources'] - source_keys.extend(extra_sources_for_rules) + source_keys = {'sources'} + source_keys.update(extra_sources_for_rules) for source_key in source_keys: for source in target_dict.get(source_key, []): (source_root, source_extension) = os.path.splitext(source) @@ -2594,46 +2250,34 @@ def ValidateRulesInTarget(target, target_dict, extra_sources_for_rules): rule['rule_sources'] = rule_sources -def ValidateRunAsInTarget(target, target_dict, build_file): +def ValidateRunAsInTarget(target_dict, build_file): target_name = target_dict.get('target_name') run_as = target_dict.get('run_as') if not run_as: return 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)) + raise GypError("The 'run_as' in target %s from file %s should be a dictionary." % (target_name, build_file)) action = run_as.get('action') if not action: - raise GypError("The 'run_as' in target %s from file %s must have an " - "'action' section." % - (target_name, build_file)) + raise GypError("The 'run_as' in target %s from file %s must have an 'action' section." % (target_name, build_file)) 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)) + 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 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)) + 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 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)) + raise GypError("The 'environment' for 'run_as' in target %s in file %s should be a dictionary." % (target_name, build_file)) -def ValidateActionsInTarget(target, target_dict, build_file): - '''Validates the inputs to the actions in a target.''' +def ValidateActionsInTarget(target_dict): + """Validates the inputs to the actions in a target.""" target_name = target_dict.get('target_name') actions = target_dict.get('actions', []) for action in actions: action_name = action.get('action_name') if not action_name: - raise GypError("Anonymous action in target %s. " - "An action must have an 'action_name' field." % - target_name) + raise GypError("Anonymous action in target %s. An action must have an 'action_name' field." % target_name) inputs = action.get('inputs', None) if inputs is None: raise GypError('Action in target %s has no inputs.' % target_name) @@ -2664,8 +2308,7 @@ def TurnIntIntoStrInDict(the_dict): def TurnIntIntoStrInList(the_list): """Given list the_list, recursively converts all integers into strings. """ - for index in xrange(0, len(the_list)): - item = the_list[index] + for index, item in enumerate(the_list): if type(item) is int: the_list[index] = str(item) elif type(item) is dict: @@ -2674,8 +2317,7 @@ def TurnIntIntoStrInList(the_list): TurnIntIntoStrInList(item) -def PruneUnwantedTargets(targets, flat_list, dependency_nodes, root_targets, - data): +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: @@ -2699,9 +2341,7 @@ def PruneUnwantedTargets(targets, flat_list, dependency_nodes, root_targets, continue new_targets = [] for target in data[build_file]['targets']: - qualified_name = gyp.common.QualifiedTarget(build_file, - target['target_name'], - target['toolset']) + 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 @@ -2748,15 +2388,13 @@ def SetGeneratorGlobals(generator_input_info): non_configuration_keys.extend(generator_input_info['non_configuration_keys']) global multiple_toolsets - multiple_toolsets = generator_input_info[ - 'generator_supports_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): +def Load(build_files, variables, includes, depth, generator_input_info, root_targets): SetGeneratorGlobals(generator_input_info) # A generator can have other lists (in addition to sources) be processed # for rules. @@ -2769,22 +2407,17 @@ def Load(build_files, variables, includes, depth, generator_input_info, check, # NOTE: data contains both "target" files (.gyp) and "includes" (.gypi), as # 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()} + data = {'target_build_files': OrderedSet()} # 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 + build_files = OrderedSet(map(os.path.normpath, build_files)) + aux_data = OrderedDict() + for build_file in build_files: + try: + LoadTargetBuildFile(build_file, data, aux_data, variables, includes, depth, True) + except Exception as 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) @@ -2804,7 +2437,7 @@ def Load(build_files, variables, includes, depth, generator_input_info, check, RemoveLinkDependenciesFromNoneTargets(targets) # Apply exclude (!) and regex (/) list filters only for dependency_sections. - for target_name, target_dict in targets.iteritems(): + for target_name, target_dict in targets.items(): tmp_dict = {} for key_base in dependency_sections: for op in ('', '!', '/'): @@ -2820,26 +2453,20 @@ def Load(build_files, variables, includes, depth, generator_input_info, check, # Make sure every dependency appears at most once. RemoveDuplicateDependencies(targets) - if circular_check: - # Make sure that any targets in a.gyp don't contain dependencies in other - # .gyp files that further depend on a.gyp. - VerifyNoGYPFileCircularDependencies(targets) + VerifyNoGYPFileCircularDependencies(targets) [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) + 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) # Handle dependent settings of various types. - for settings_type in ['all_dependent_settings', - 'direct_dependent_settings', - 'link_settings']: + for settings_type in ['all_dependent_settings', 'direct_dependent_settings', 'link_settings']: DoDependentSettings(settings_type, flat_list, targets, dependency_nodes) # Take out the dependent settings now that they've been published to all @@ -2853,15 +2480,13 @@ def Load(build_files, variables, includes, depth, generator_input_info, check, # that they need so that their link steps will be correct. gii = generator_input_info if gii['generator_wants_static_library_dependencies_adjusted']: - AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes, - gii['generator_wants_sorted_dependencies']) + AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes, gii['generator_wants_sorted_dependencies']) # Apply "post"/"late"/"target" variable expansions and condition evaluations. for target in flat_list: target_dict = targets[target] build_file = gyp.common.BuildFile(target) - ProcessVariablesAndConditionsInDict( - target_dict, PHASE_LATE, variables, build_file) + ProcessVariablesAndConditionsInDict(target_dict, PHASE_LATE, variables, build_file) # Move everything that can go into a "configurations" section into one. for target in flat_list: @@ -2877,8 +2502,7 @@ def Load(build_files, variables, includes, depth, generator_input_info, check, for target in flat_list: target_dict = targets[target] build_file = gyp.common.BuildFile(target) - ProcessVariablesAndConditionsInDict( - target_dict, PHASE_LATELATE, variables, build_file) + ProcessVariablesAndConditionsInDict(target_dict, PHASE_LATELATE, variables, build_file) # Make sure that the rules make sense, and build up rule_sources lists as # needed. Not all generators will need to use the rule_sources lists, but @@ -2888,11 +2512,10 @@ def Load(build_files, variables, includes, depth, generator_input_info, check, target_dict = targets[target] build_file = gyp.common.BuildFile(target) ValidateTargetType(target, target_dict) - ValidateSourcesInTarget(target, target_dict, build_file, - duplicate_basename_check) + ValidateSourcesInTarget(target, target_dict) ValidateRulesInTarget(target, target_dict, extra_sources_for_rules) - ValidateRunAsInTarget(target, target_dict, build_file) - ValidateActionsInTarget(target, target_dict, build_file) + ValidateRunAsInTarget(target_dict, build_file) + ValidateActionsInTarget(target_dict) # Generators might not expect ints. Turn them into strs. TurnIntIntoStrInDict(data) diff --git a/tools/gyp/gyp/lib/__init__.py b/tools/gyp/gyp/lib/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/pylib/gyp/ninja_syntax.py b/tools/gyp/gyp/lib/ninja_syntax.py similarity index 100% rename from tools/gyp/pylib/gyp/ninja_syntax.py rename to tools/gyp/gyp/lib/ninja_syntax.py diff --git a/tools/gyp/pylib/gyp/simple_copy.py b/tools/gyp/gyp/lib/simple_copy.py similarity index 63% rename from tools/gyp/pylib/gyp/simple_copy.py rename to tools/gyp/gyp/lib/simple_copy.py index 74c98c5a79594b..188434e8bbaec7 100644 --- a/tools/gyp/pylib/gyp/simple_copy.py +++ b/tools/gyp/gyp/lib/simple_copy.py @@ -6,6 +6,8 @@ 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.""" +from collections import OrderedDict + class Error(Exception): pass @@ -20,16 +22,26 @@ def deepcopy(x): 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)) + 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): +try: + # noinspection PyUnresolvedReferences + _string_types = (str, unicode) +except NameError: + _string_types = (str, ) + +try: + # noinspection PyUnresolvedReferences + _integer_types = (int, long) +except NameError: + _integer_types = (int, ) + +for x in (type(None), float, bool, type) + _integer_types + _string_types: d[x] = _deepcopy_atomic def _deepcopy_list(x): @@ -38,9 +50,16 @@ def _deepcopy_list(x): def _deepcopy_dict(x): y = {} - for key, value in x.iteritems(): + for key, value in x.items(): y[deepcopy(key)] = deepcopy(value) return y d[dict] = _deepcopy_dict +def _deepcopy_ordered_dict(x): + y = OrderedDict() + for key, value in x.items(): + y[deepcopy(key)] = deepcopy(value) + return y +d[OrderedDict] = _deepcopy_ordered_dict + del d diff --git a/tools/gyp/pylib/gyp/msvs_emulation.py b/tools/gyp/gyp/msvs_emulation.py similarity index 67% rename from tools/gyp/pylib/gyp/msvs_emulation.py rename to tools/gyp/gyp/msvs_emulation.py index 4acaee24469594..c525af4509f4eb 100644 --- a/tools/gyp/pylib/gyp/msvs_emulation.py +++ b/tools/gyp/gyp/msvs_emulation.py @@ -7,18 +7,33 @@ build systems, primarily ninja. """ +import codecs import os +import pickle import re import subprocess import sys +import time +import hashlib +import traceback +from collections import Iterable, OrderedDict +from tempfile import gettempdir -from gyp.common import OrderedSet -import gyp.MSVSUtil -import gyp.MSVSVersion +from gyp import DebugOutput, DEBUG_GENERAL +from gyp.common import EnsureDirExists, WriteOnDiff, memoize +from gyp.MSVS import TARGET_TYPE_EXT, TryQueryRegistryValue +if 'basestring' not in __builtins__: + basestring = str windows_quoter_regex = re.compile(r'(\\*)"') +utf8encoder = codecs.getencoder('utf-8') +def encode(s): + return utf8encoder(s)[0] + +NUL = bytes([0]) + def QuoteForRspFile(arg): """Quote a command line argument so that it appears as one argument when @@ -37,7 +52,7 @@ def QuoteForRspFile(arg): # For a literal quote, CommandLineToArgvW requires 2n+1 backslashes # preceding it, and results in n backslashes + the quote. So we substitute # in 2* what we match, +1 more, plus the quote. - arg = windows_quoter_regex.sub(lambda mo: 2 * mo.group(1) + '\\"', arg) + arg = windows_quoter_regex.sub(lambda mo: 2 * str(mo.group(1)) + '\\"', arg) # %'s also need to be doubled otherwise they're interpreted as batch # positional arguments. Also make sure to escape the % so that they're @@ -84,23 +99,22 @@ def _AddPrefix(element, prefix): """Add |prefix| to |element| or each subelement if element is iterable.""" if element is None: return element - # Note, not Iterable because we don't want to handle strings like that. - if isinstance(element, list) or isinstance(element, tuple): + if isinstance(element, Iterable) and not isinstance(element, basestring): return [prefix + e for e in element] else: return prefix + element -def _DoRemapping(element, map): +def _DoRemapping(element, map_arg): """If |element| then remap it through |map|. If |element| is iterable then each item will be remapped. Any elements not found will be removed.""" - if map is not None and element is not None: - if not callable(map): - map = map.get # Assume it's a dict, otherwise a callable to do the remap. - if isinstance(element, list) or isinstance(element, tuple): - element = filter(None, [map(elem) for elem in element]) + if map_arg is not None and element is not None: + if not callable(map_arg): + map_arg = map_arg.get # Assume it's a dict, otherwise a callable to do the remap. + if isinstance(element, Iterable) and not isinstance(element, basestring): + element = filter(None, [map_arg(elem) for elem in element]) else: - element = map(element) + element = map_arg(element) return element @@ -109,7 +123,7 @@ def _AppendOrReturn(append, element): then add |element| to it, adding each item in |element| if it's a list or tuple.""" if append is not None and element is not None: - if isinstance(element, list) or isinstance(element, tuple): + if isinstance(element, Iterable) and not isinstance(element, basestring): append.extend(element) else: append.append(element) @@ -117,76 +131,18 @@ def _AppendOrReturn(append, element): return element +@memoize def _FindDirectXInstallation(): - """Try to find an installation location for the DirectX SDK. Check for the + """ + Try to find an installation location for the DirectX SDK. Check for the standard environment variable, and if that doesn't exist, try to find - via the registry. May return None if not found in either location.""" - # Return previously calculated value, if there is one - if hasattr(_FindDirectXInstallation, 'dxsdk_dir'): - return _FindDirectXInstallation.dxsdk_dir - - dxsdk_dir = os.environ.get('DXSDK_DIR') - if not dxsdk_dir: - # Setup params to pass to and attempt to launch reg.exe. - cmd = ['reg.exe', 'query', r'HKLM\Software\Microsoft\DirectX', '/s'] - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - for line in p.communicate()[0].splitlines(): - if 'InstallPath' in line: - dxsdk_dir = line.split(' ')[3] + "\\" - - # Cache return value - _FindDirectXInstallation.dxsdk_dir = dxsdk_dir + via the registry. May return None if not found in either location. + """ + dxsdk_dir = os.environ.get('DXSDK_DIR', TryQueryRegistryValue('Software\Microsoft\DirectX', 'InstallPath')) 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 - - +# noinspection PyUnresolvedReferences 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 @@ -209,7 +165,7 @@ def __init__(self, spec, generator_flags): configs = spec['configurations'] for field, default in supported_fields: setattr(self, field, {}) - for configname, config in configs.iteritems(): + for configname, config in configs.items(): getattr(self, field)[configname] = config.get(field, default()) self.msvs_cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.']) @@ -222,11 +178,13 @@ def __init__(self, spec, generator_flags): for field in unsupported_fields: for config in configs.values(): if field in config: - unsupported += ["%s not supported (target %s)." % - (field, spec['target_name'])] + unsupported += ["%s not supported (target %s)." % (field, spec['target_name'])] if unsupported: raise Exception('\n'.join(unsupported)) + self.msvs_configuration_platform = {} + self.msvs_target_platform = {} + def GetExtension(self): """Returns the extension for the target, with no leading dot. @@ -236,18 +194,21 @@ def GetExtension(self): ext = self.spec.get('product_extension', None) if ext: return ext - return gyp.MSVSUtil.TARGET_TYPE_EXT.get(self.spec['type'], '') + return 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.""" - target_platform = 'Win32' if self.GetArch(config) == 'x86' else 'x64' - target_name = self.spec.get('product_prefix', '') + \ - self.spec.get('product_name', self.spec['target_name']) + target_arch = self.GetArch(config) + if target_arch == 'x86': + target_platform = 'Win32' + else: + target_platform = target_arch + 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 - + VSInstallDir = self.vs_version.path or '' replacements = { '$(InputName)': '${root}', '$(InputPath)': '${source}', @@ -261,8 +222,19 @@ def GetVSMacroEnv(self, base_to_build=None, config=None): '$(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. + '$(VSInstallDir)': VSInstallDir, + '$(VCInstallDir)': os.path.join(VSInstallDir, '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() or '', + # Try to find an installation location for the Windows DDK by checking + # the WDK_DIR environment variable, may be None. + '$(WDK_DIR)': os.environ.get('WDK_DIR', ''), } - replacements.update(GetGlobalVSMacroEnv(self.vs_version)) return replacements def ConvertVSMacros(self, s, base_to_build=None, config=None): @@ -270,19 +242,20 @@ def ConvertVSMacros(self, s, base_to_build=None, config=None): env = self.GetVSMacroEnv(base_to_build, config=config) return ExpandMacros(s, env) - def AdjustLibraries(self, libraries): + @staticmethod + def AdjustLibraries(libraries): """Strip -l from library if it's specified with that.""" libs = [lib[2:] if lib.startswith('-l') else lib for lib in libraries] - return [lib + '.lib' if not lib.lower().endswith('.lib') \ - and not lib.lower().endswith('.obj') else lib for lib in libs] + return [lib + '.lib' if not lib.lower().endswith('.lib') else lib for lib in libs] - def _GetAndMunge(self, field, path, default, prefix, append, map): + @staticmethod + def _GetAndMunge(field, path, default, prefix, append, map_arg): """Retrieve a value from |field| at |path| or return |default|. If |append| is specified, and the item is found, it will be appended to that object instead of returned. If |map| is specified, results will be remapped through |map| before being returned or appended.""" result = _GenericRetrieve(field, default, path) - result = _DoRemapping(result, map) + result = _DoRemapping(result, map_arg) result = _AddPrefix(result, prefix) return _AppendOrReturn(append, result) @@ -292,19 +265,21 @@ def __init__(self, parent, field, base_path, append=None): self.field = field self.base_path = [base_path] self.append = append + + # noinspection PyShadowingBuiltins def __call__(self, name, map=None, prefix='', default=None): - return self.parent._GetAndMunge(self.field, self.base_path + [name], - default=default, prefix=prefix, append=self.append, map=map) + # noinspection PyProtectedMember + return self.parent._GetAndMunge(self.field, self.base_path + [name], default=default, prefix=prefix, append=self.append, map_arg=map) def GetArch(self, config): """Get architecture based on msvs_configuration_platform and msvs_target_platform. Returns either 'x86' or 'x64'.""" configuration_platform = self.msvs_configuration_platform.get(config, '') platform = self.msvs_target_platform.get(config, '') - if not platform: # If no specific override, use the configuration's. + if not platform: # If no specific override, use the configuration's. platform = configuration_platform # Map from platform to architecture. - return {'Win32': 'x86', 'x64': 'x64'}.get(platform, 'x86') + return {'Win32': 'x86', 'x64': 'x64', 'ARM64': 'arm64'}.get(platform, 'x86') def _TargetConfig(self, config): """Returns the target-specific configuration.""" @@ -312,7 +287,7 @@ def _TargetConfig(self, config): # first level is globally for the configuration (this is what we consider # "the" config at the gyp level, which will be something like 'Debug' or # 'Release'), VS2015 and later only use this level - if self.vs_version.short_name >= 2015: + if self.vs_version.short_name >= '2015': return config # and a second target-specific configuration, which is an # override for the global one. |config| is remapped here to take into @@ -324,26 +299,20 @@ def _TargetConfig(self, config): config = config.rsplit('_', 1)[0] return config - def _Setting(self, path, config, - default=None, prefix='', append=None, map=None): + def _Setting(self, path, config, default=None, prefix='', append=None, map_arg=None): """_GetAndMunge for msvs_settings.""" - return self._GetAndMunge( - self.msvs_settings[config], path, default, prefix, append, map) + return self._GetAndMunge(self.msvs_settings[config], path, default, prefix, append, map_arg) - def _ConfigAttrib(self, path, config, - default=None, prefix='', append=None, map=None): + def _ConfigAttrib(self, path, config, default=None, prefix='', append=None, map_arg=None): """_GetAndMunge for msvs_configuration_attributes.""" - return self._GetAndMunge( - self.msvs_configuration_attributes[config], - path, default, prefix, append, map) + return self._GetAndMunge(self.msvs_configuration_attributes[config], path, default, prefix, append, map_arg) def AdjustIncludeDirs(self, include_dirs, config): """Updates include_dirs to expand VS specific paths, and adds the system include dirs used for platform SDK and similar.""" config = self._TargetConfig(config) includes = include_dirs + self.msvs_system_include_dirs[config] - includes.extend(self._Setting( - ('VCCLCompilerTool', 'AdditionalIncludeDirectories'), config, default=[])) + includes.extend(self._Setting(('VCCLCompilerTool', 'AdditionalIncludeDirectories'), config, default=[])) return [self.ConvertVSMacros(p, config=config) for p in includes] def AdjustMidlIncludeDirs(self, midl_include_dirs, config): @@ -351,8 +320,7 @@ def AdjustMidlIncludeDirs(self, midl_include_dirs, config): 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=[])) + includes.extend(self._Setting(('VCMIDLTool', 'AdditionalIncludeDirectories'), config, default=[])) return [self.ConvertVSMacros(p, config=config) for p in includes] def GetComputedDefines(self, config): @@ -364,16 +332,14 @@ def GetComputedDefines(self, config): defines.extend(('_UNICODE', 'UNICODE')) if self._ConfigAttrib(['CharacterSet'], config) == '2': defines.append('_MBCS') - defines.extend(self._Setting( - ('VCCLCompilerTool', 'PreprocessorDefinitions'), config, default=[])) + defines.extend(self._Setting(('VCCLCompilerTool', 'PreprocessorDefinitions'), config, default=[])) return defines def GetCompilerPdbName(self, config, expand_special): """Get the pdb file name that should be used for compiler invocations, or None if there's no explicit name specified.""" config = self._TargetConfig(config) - pdbname = self._Setting( - ('VCCLCompilerTool', 'ProgramDataBaseFileName'), config) + pdbname = self._Setting(('VCCLCompilerTool', 'ProgramDataBaseFileName'), config) if pdbname: pdbname = expand_special(self.ConvertVSMacros(pdbname)) return pdbname @@ -391,13 +357,12 @@ def GetOutputName(self, config, expand_special): """Gets the explicitly overridden output name for a target or returns None if it's not overridden.""" config = self._TargetConfig(config) - type = self.spec['type'] - root = 'VCLibrarianTool' if type == 'static_library' else 'VCLinkerTool' + spec_type = self.spec['type'] + root = 'VCLibrarianTool' if spec_type == 'static_library' else 'VCLinkerTool' # TODO(scottmg): Handle OutputDirectory without OutputFile. output_file = self._Setting((root, 'OutputFile'), config) if output_file: - output_file = expand_special(self.ConvertVSMacros( - output_file, config=config)) + output_file = expand_special(self.ConvertVSMacros(output_file, config=config)) return output_file def GetPDBName(self, config, expand_special, default): @@ -405,8 +370,7 @@ def GetPDBName(self, config, expand_special, default): default if it's not overridden, or if no pdb will be generated.""" config = self._TargetConfig(config) output_file = self._Setting(('VCLinkerTool', 'ProgramDatabaseFile'), config) - generate_debug_info = self._Setting( - ('VCLinkerTool', 'GenerateDebugInformation'), config) + 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)) @@ -436,10 +400,8 @@ def GetCflags(self, config): config = self._TargetConfig(config) cflags = [] cflags.extend(['/wd' + w for w in self.msvs_disabled_warnings[config]]) - cl = self._GetWrapper(self, self.msvs_settings[config], - 'VCCLCompilerTool', append=cflags) - cl('Optimization', - map={'0': 'd', '1': '1', '2': '2', '3': 'x'}, prefix='/O', default='2') + cl = self._GetWrapper(self, self.msvs_settings[config], 'VCCLCompilerTool', append=cflags) + 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'}) @@ -447,42 +409,33 @@ def GetCflags(self, config): 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('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('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-'}) cl('EnableFunctionLevelLinking', map={'true': '/Gy', 'false': '/Gy-'}) cl('MinimalRebuild', map={'true': '/Gm'}) cl('BufferSecurityCheck', map={'true': '/GS', 'false': '/GS-'}) cl('BasicRuntimeChecks', map={'1': 's', '2': 'u', '3': '1'}, prefix='/RTC') - cl('RuntimeLibrary', - map={'0': 'T', '1': 'Td', '2': 'D', '3': 'Dd'}, prefix='/M') - cl('ExceptionHandling', map={'1': 'sc','2': 'a'}, prefix='/EH') + cl('RuntimeLibrary', map={'0': 'T', '1': 'Td', '2': 'D', '3': 'Dd'}, prefix='/M') + cl('ExceptionHandling', map={'1': 'sc', '2': 'a'}, prefix='/EH') cl('DefaultCharIsUnsigned', map={'true': '/J'}) - cl('TreatWChar_tAsBuiltInType', - map={'false': '-', 'true': ''}, prefix='/Zc:wchar_t') + cl('TreatWChar_tAsBuiltInType', 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.project_version >= 12.0: + 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.project_version >= '12.0': # New flag introduced in VS2013 (project version 12.0) Forces writes to # the program database (PDB) to be serialized through MSPDBSRV.EXE. # https://msdn.microsoft.com/en-us/library/dn502518.aspx 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) + cflags = [x for x in cflags if not x.startswith('/MP')] return cflags def _GetPchFlags(self, config, extension): @@ -498,7 +451,7 @@ def _GetPchFlags(self, config, extension): pch = self.msvs_precompiled_header[config] pchbase = os.path.split(pch)[1] return ['/Yu' + pch, '/FI' + pch, '/Fp${pchprefix}.' + pchbase + '.pch'] - return [] + return [] def GetCflagsC(self, config): """Returns the flags that need to be added to .c compilations.""" @@ -514,24 +467,21 @@ def _GetAdditionalLibraryDirectories(self, root, config, gyp_to_build_path): """Get and normalize the list of paths in AdditionalLibraryDirectories setting.""" config = self._TargetConfig(config) - libpaths = self._Setting((root, 'AdditionalLibraryDirectories'), - config, default=[]) - libpaths = [os.path.normpath( - gyp_to_build_path(self.ConvertVSMacros(p, config=config))) - for p in libpaths] + libpaths = self._Setting((root, 'AdditionalLibraryDirectories'), config, default=[]) + libpaths = [os.path.normpath(gyp_to_build_path(self.ConvertVSMacros(p, config=config))) for p in libpaths] return ['/LIBPATH:"' + p + '"' for p in libpaths] def GetLibFlags(self, config, gyp_to_build_path): """Returns the flags that need to be added to lib commands.""" config = self._TargetConfig(config) libflags = [] - lib = self._GetWrapper(self, self.msvs_settings[config], - 'VCLibrarianTool', append=libflags) - libflags.extend(self._GetAdditionalLibraryDirectories( - 'VCLibrarianTool', config, gyp_to_build_path)) + lib = self._GetWrapper(self, self.msvs_settings[config], 'VCLibrarianTool', append=libflags) + 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:') + # TODO: These 'map' values come from machineTypeOption enum, + # and does not have an official value for ARM64 in VS2017 (yet). + # It needs to verify the ARM64 value when machineTypeOption is updated. + lib('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM', '18': 'ARM64'}, prefix='/MACHINE:') lib('AdditionalOptions') return libflags @@ -539,8 +489,7 @@ def GetDefFile(self, gyp_to_build_path): """Returns the .def file from sources, if any. Otherwise returns None.""" spec = self.spec if spec['type'] in ('shared_library', 'loadable_module', 'executable'): - def_files = [s for s in spec.get('sources', []) - if s.lower().endswith('.def')] + def_files = [s for s in spec.get('sources', []) if s.lower().endswith('.def')] if len(def_files) == 1: return gyp_to_build_path(def_files[0]) elif len(def_files) > 1: @@ -558,30 +507,26 @@ 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) + output_file = self._Setting(('VCLinkerTool', 'ProfileGuidedDatabase'), config) if output_file: - output_file = expand_special(self.ConvertVSMacros( - output_file, config=config)) + 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, output_name, is_executable, build_dir): + def GetLdflags(self, config, gyp_to_build_path, expand_special, 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) ldflags = [] - ld = self._GetWrapper(self, self.msvs_settings[config], - 'VCLinkerTool', append=ldflags) + ld = self._GetWrapper(self, self.msvs_settings[config], 'VCLinkerTool', append=ldflags) self._GetDefFileAsLdflags(ldflags, gyp_to_build_path) ld('GenerateDebugInformation', map={'true': '/DEBUG'}) - ld('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM'}, - prefix='/MACHINE:') - ldflags.extend(self._GetAdditionalLibraryDirectories( - 'VCLinkerTool', config, gyp_to_build_path)) + # TODO: These 'map' values come from machineTypeOption enum, + # and does not have an official value for ARM64 in VS2017 (yet). + # It needs to verify the ARM64 value when machineTypeOption is updated. + ld('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM', '18': 'ARM64'}, prefix='/MACHINE:') + ldflags.extend(self._GetAdditionalLibraryDirectories('VCLinkerTool', config, gyp_to_build_path)) ld('DelayLoadDLLs', prefix='/DELAYLOAD:') - ld('TreatLinkerWarningAsErrors', prefix='/WX', - map={'true': '', 'false': ':NO'}) + ld('TreatLinkerWarningAsErrors', prefix='/WX', map={'true': '', 'false': ':NO'}) out = self.GetOutputName(config, expand_special) if out: ldflags.append('/OUT:' + out) @@ -592,25 +537,18 @@ def GetLdflags(self, config, gyp_to_build_path, 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('GenerateMapFile', map={'true': '/MAP:' + map_file if map_file else '/MAP'}) ld('MapExports', map={'true': '/MAPINFO:EXPORTS'}) ld('AdditionalOptions', prefix='') - minimum_required_version = self._Setting( - ('VCLinkerTool', 'MinimumRequiredVersion'), config, default='') + 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:') + 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='') + stack_reserve_size = self._Setting(('VCLinkerTool', 'StackReserveSize'), config, default='') if stack_reserve_size: - stack_commit_size = self._Setting( - ('VCLinkerTool', 'StackCommitSize'), config, default='') + 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)) @@ -619,23 +557,17 @@ def GetLdflags(self, config, gyp_to_build_path, expand_special, 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('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': '', '2': ':PGINSTRUMENT', '3': ':PGOPTIMIZE', - '4': ':PGUPDATE'}, - prefix='/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:') ld('Profile', map={'true': '/PROFILE'}) - ld('LargeAddressAware', - map={'1': ':NO', '2': ''}, prefix='/LARGEADDRESSAWARE') + ld('LargeAddressAware', map={'1': ':NO', '2': ''}, prefix='/LARGEADDRESSAWARE') # TODO(scottmg): This should sort of be somewhere else (not really a flag). ld('AdditionalDependencies', prefix='') @@ -643,33 +575,26 @@ def GetLdflags(self, config, gyp_to_build_path, expand_special, safeseh_default = 'true' else: safeseh_default = None - ld('ImageHasSafeExceptionHandlers', - map={'false': ':NO', 'true': ''}, prefix='/SAFESEH', - default=safeseh_default) + 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', - ldflags) - if not base_flags: + if not any('DYNAMICBASE' in flag or flag == '/FIXED' for flag in ldflags): ldflags.append('/DYNAMICBASE') # If the NXCOMPAT flag has not been specified, default to on. Despite the # documentation that says this only defaults to on when the subsystem is # Vista or greater (which applies to the linker), the IDE defaults it on # unless it's explicitly off. - if not filter(lambda x: 'NXCOMPAT' in x, ldflags): + if not any('NXCOMPAT' in flag for flag in ldflags): ldflags.append('/NXCOMPAT') - have_def_file = filter(lambda x: x.startswith('/DEF:'), ldflags) - 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) + have_def_file = any(flag.startswith('/DEF:') for flag in ldflags) + 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) return ldflags, intermediate_manifest, manifest_files - def _GetLdManifestFlags(self, config, name, gyp_to_build_path, - allow_isolation, build_dir): + 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 @@ -677,9 +602,7 @@ def _GetLdManifestFlags(self, config, name, gyp_to_build_path, 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') + 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 @@ -687,10 +610,6 @@ def _GetLdManifestFlags(self, config, name, gyp_to_build_path, return ['/MANIFEST:NO'], [], [] 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 @@ -699,29 +618,24 @@ def _GetLdManifestFlags(self, config, name, gyp_to_build_path, # 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. + flags = ['/MANIFEST', '/ManifestFile:' + output_name, '/MANIFESTUAC:NO'] # 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" \ -"" + enable_uac = self._Setting(('VCLinkerTool', 'EnableUAC'), config, default='true') + generated_manifest_outer = "" \ + "%s" \ + "" if enable_uac == 'true': - execution_level = self._Setting(('VCLinkerTool', 'UACExecutionLevel'), - config, default='0') + execution_level = self._Setting(('VCLinkerTool', 'UACExecutionLevel'), config, default='0') execution_level_map = { '0': 'asInvoker', '1': 'highestAvailable', '2': 'requireAdministrator' } - ui_access = self._Setting(('VCLinkerTool', 'UACUIAccess'), config, - default='false') + ui_access = self._Setting(('VCLinkerTool', 'UACUIAccess'), config, default='false') inner = ''' @@ -742,8 +656,8 @@ def _GetLdManifestFlags(self, config, name, gyp_to_build_path, # 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) + EnsureDirExists(build_dir_generated_name) + f = WriteOnDiff(build_dir_generated_name) f.write(generated_manifest_contents) f.close() manifest_files = [generated_name] @@ -751,20 +665,16 @@ def _GetLdManifestFlags(self, config, name, gyp_to_build_path, if allow_isolation: flags.append('/ALLOWISOLATION') - manifest_files += self._GetAdditionalManifestFiles(config, - gyp_to_build_path) + 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 generated by the linker.""" - files = self._Setting(('VCManifestTool', 'AdditionalManifestFiles'), config, - default=[]) + files = self._Setting(('VCManifestTool', 'AdditionalManifestFiles'), config, default=[]) if isinstance(files, str): files = files.split(';') - return [os.path.normpath( - gyp_to_build_path(self.ConvertVSMacros(f, config=config))) - for f in files] + return [os.path.normpath(gyp_to_build_path(self.ConvertVSMacros(f, config=config))) for f in files] def IsUseLibraryDependencyInputs(self, config): """Returns whether the target should be linked via Use Library Dependency @@ -776,8 +686,7 @@ def IsUseLibraryDependencyInputs(self, config): def IsEmbedManifest(self, config): """Returns whether manifest should be linked into binary.""" config = self._TargetConfig(config) - embed = self._Setting(('VCManifestTool', 'EmbedManifest'), config, - default='true') + embed = self._Setting(('VCManifestTool', 'EmbedManifest'), config, default='true') return embed == 'true' def IsLinkIncremental(self, config): @@ -791,8 +700,7 @@ def GetRcflags(self, config, gyp_to_ninja_path): compiler.""" config = self._TargetConfig(config) rcflags = [] - rc = self._GetWrapper(self, self.msvs_settings[config], - 'VCResourceCompilerTool', append=rcflags) + rc = self._GetWrapper(self, self.msvs_settings[config], 'VCResourceCompilerTool', append=rcflags) rc('AdditionalIncludeDirectories', map=gyp_to_ninja_path, prefix='/I') rcflags.append('/I' + gyp_to_ninja_path('.')) rc('PreprocessorDefinitions', prefix='/d') @@ -809,54 +717,51 @@ def BuildCygwinBashCommandLine(self, args, path_to_base): contain ninja variables cannot be fixed here (for example ${source}), so the outer generator needs to make sure that the paths that are written out are in posix style, if the command line will be used here.""" - cygwin_dir = os.path.normpath( - os.path.join(path_to_base, self.msvs_cygwin_dirs[0])) + cygwin_dir = os.path.normpath(os.path.join(path_to_base, self.msvs_cygwin_dirs[0])) cd = ('cd %s' % path_to_base).replace('\\', '/') args = [a.replace('\\', '/').replace('"', '\\"') for a in args] args = ["'%s'" % a.replace("'", "'\\''") for a in args] bash_cmd = ' '.join(args) - cmd = ( - 'call "%s\\setup_env.bat" && set CYGWIN=nontsec && ' % cygwin_dir + - 'bash -c "%s ; %s"' % (cd, bash_cmd)) + cmd = ('call "%s\\setup_env.bat" && set CYGWIN=nontsec && ' % cygwin_dir + 'bash -c "%s ; %s"' % (cd, bash_cmd)) return cmd def IsRuleRunUnderCygwin(self, rule): """Determine if an action should be run under cygwin. If the variable is unset, or set to 1 we use cygwin.""" - return int(rule.get('msvs_cygwin_shell', - self.spec.get('msvs_cygwin_shell', 1))) != 0 + return int(rule.get('msvs_cygwin_shell', self.spec.get('msvs_cygwin_shell', 1))) != 0 - def _HasExplicitRuleForExtension(self, spec, extension): + @staticmethod + def _HasExplicitRuleForExtension(spec, extension): """Determine if there's an explicit rule for a particular extension.""" for rule in spec.get('rules', []): - if rule['extension'] == extension: + if rule.get('extension') == extension: return True return False - def _HasExplicitIdlActions(self, spec): + @staticmethod + def _HasExplicitIdlActions(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', [])]) + 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)) + 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 need to generate implicit rules to assemble .asm files.""" return self._HasExplicitRuleForExtension(spec, 'asm') - def GetIdlBuildData(self, source, config): + def GetIdlBuildData(self, _, config): """Determine the implicit outputs for an idl file. Returns output directory, outputs, and variables and flags that are required.""" config = self._TargetConfig(config) midl_get = self._GetWrapper(self, self.msvs_settings[config], 'VCMIDLTool') + def midl(name, default=None): - return self.ConvertVSMacros(midl_get(name, default=default), - config=config) + return self.ConvertVSMacros(midl_get(name, default=default), config=config) + tlb = midl('TypeLibraryName', default='${root}.tlb') header = midl('HeaderFileName', default='${root}.h') dlldata = midl('DLLDataFileName', default='dlldata.c') @@ -866,13 +771,11 @@ def midl(name, default=None): # generated depending on the content of the input idl file. outdir = midl('OutputDirectory', default='') output = [header, dlldata, iid, proxy] - variables = [('tlb', tlb), - ('h', header), - ('dlldata', dlldata), - ('iid', iid), - ('proxy', proxy)] + variables = [('tlb', tlb), ('h', header), ('dlldata', dlldata), ('iid', iid), ('proxy', proxy)] # TODO(scottmg): Are there configuration settings to set these flags? - target_platform = 'win32' if self.GetArch(config) == 'x86' else 'x64' + target_platform = self.GetArch(config) + if target_platform == 'x86': + target_platform = 'win32' flags = ['/char', 'signed', '/env', target_platform, '/Oicf'] return outdir, output, variables, flags @@ -888,8 +791,8 @@ class PrecompiledHeader(object): """Helper to generate dependencies and build rules to handle generation of precompiled headers. Interface matches the GCH handler in xcode_emulation.py. """ - def __init__( - self, settings, config, gyp_to_build_path, gyp_to_unique_output, obj_ext): + + def __init__(self, settings, config, gyp_to_build_path, gyp_to_unique_output, obj_ext): self.settings = settings self.config = config pch_source = self.settings.msvs_precompiled_source[self.config] @@ -902,7 +805,7 @@ def _PchHeader(self): files.""" return self.settings.msvs_precompiled_header[self.config] - def GetObjDependencies(self, sources, objs, arch): + def GetObjDependencies(self, sources, _, 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 compatibility @@ -916,49 +819,49 @@ def GetObjDependencies(self, sources, objs, arch): return [(None, None, self.output_obj)] return [] - def GetPchBuildCommands(self, arch): + @staticmethod + def GetPchBuildCommands(_): """Not used on Windows as there are no additional build steps required (instead, existing steps are modified in GetFlagsModifications below).""" return [] - def GetFlagsModifications(self, input, output, implicit, command, - cflags_c, cflags_cc, expand_special): + def GetFlagsModifications(self, input_arg, output, implicit, command, cflags_c, cflags_cc, expand_special): """Get the modified cflags and implicit dependencies that should be used for the pch compilation step.""" - if input == self.pch_source: + if input_arg == self.pch_source: pch_output = ['/Yc' + self._PchHeader()] if command == 'cxx': - return ([('cflags_cc', map(expand_special, cflags_cc + pch_output))], - self.output_obj, []) + return [('cflags_cc', map(expand_special, cflags_cc + pch_output))], self.output_obj, [] elif command == 'cc': - return ([('cflags_c', map(expand_special, cflags_c + pch_output))], - self.output_obj, []) + return [('cflags_c', map(expand_special, cflags_c + pch_output))], self.output_obj, [] return [], output, implicit -vs_version = None +default_vs_version = None def GetVSVersion(generator_flags): - global vs_version - if not vs_version: - vs_version = gyp.MSVSVersion.SelectVisualStudioVersion( - generator_flags.get('msvs_version', 'auto'), - allow_fallback=False) - return vs_version + global default_vs_version + if not default_vs_version: + from gyp.MSVS import MSVSVersion + default_vs_version = MSVSVersion.SelectVisualStudioVersion(generator_flags.get('msvs_version', 'auto')) + return default_vs_version + def _GetVsvarsSetupArgs(generator_flags, arch): vs = GetVSVersion(generator_flags) - return vs.SetupScript() + return vs.SetupScript(arch) + def ExpandMacros(string, expansions): """Expand $(Variable) per expansions dict. See MsvsSettings.GetVSMacroEnv for the canonical way to retrieve a suitable dict.""" if '$' in string: - for old, new in expansions.iteritems(): + for old, new in expansions.items(): assert '$(' not in new, new string = string.replace(old, new) return string -def _ExtractImportantEnvironment(output_of_set): + +def _ExtractImportantEnvironment(output_of_set, arch): """Extracts environment variables required for the toolchain to run from a textual dump output by the cmd.exe 'set' command.""" envvars_to_save = ( @@ -972,14 +875,20 @@ def _ExtractImportantEnvironment(output_of_set): 'temp', 'tmp', ) - env = {} + env = OrderedDict() # This occasionally happens and leads to misleading SYSTEMROOT error messages # if not caught here. + cl_find = 'cl.exe' + if 'Visual Studio 201' in output_of_set: + cl_find = arch + '.' + cl_find if output_of_set.count('=') == 0: raise Exception('Invalid output_of_set. Value is:\n%s' % output_of_set) for line in output_of_set.splitlines(): + if re.search(cl_find, line, re.I): + env['GYP_CL_PATH'] = line + continue for envvar in envvars_to_save: - if re.match(envvar + '=', line.lower()): + if re.match(envvar + '=', line, re.I): var, setting = line.split('=', 1) if envvar == 'path': # Our own rules (for running gyp-win-tool) and other actions in @@ -989,34 +898,17 @@ def _ExtractImportantEnvironment(output_of_set): setting = os.path.dirname(sys.executable) + os.pathsep + setting env[var.upper()] = setting break + for required in ('SYSTEMROOT', 'TEMP', 'TMP'): if required not in env: - raise Exception('Environment variable "%s" ' - 'required to be set to valid path' % required) + raise Exception('Environment variable "%s" required to be set to valid path' % required) return env -def _FormatAsEnvironmentBlock(envvar_dict): - """Format as an 'environment block' directly suitable for CreateProcess. - Briefly this is a list of key=value\0, terminated by an additional \0. See - CreateProcess documentation for more details.""" - block = '' - nul = '\0' - for key, value in envvar_dict.iteritems(): - block += key + '=' + value + nul - block += nul - return block - -def _ExtractCLPath(output_of_where): - """Gets the path to cl.exe based on the output of calling the environment - setup batch file, followed by the equivalent of `where`.""" - # Take the first line, as that's the first found in the PATH. - for line in output_of_where.strip().splitlines(): - if line.startswith('LOC:'): - return line[len('LOC:'):].strip() - -def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, - system_includes, open_out): - """It's not sufficient to have the absolute path to the compiler, linker, + +# TODO(refack) Pass only one arch +def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags): + """ + 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 msvs_target_platform hackery). Different architectures require a different @@ -1029,45 +921,82 @@ def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, When the following procedure to generate environment files does not meet your requirement (e.g. for custom toolchains), you can pass "-G ninja_use_custom_environment_files" to the gyp to suppress file - generation and use custom environment files prepared by yourself.""" - archs = ('x86', 'x64') - if generator_flags.get('ninja_use_custom_environment_files', 0): - cl_paths = {} - for arch in archs: - cl_paths[arch] = 'cl.exe' - return cl_paths + generation and use custom environment files prepared by yourself. + + Args: + toplevel_build_dir (str): root dir of build tree + generator_flags (OrderedDict): flags passed to the generator + """ vs = GetVSVersion(generator_flags) - cl_paths = {} + + if generator_flags.get('ninja_use_custom_environment_files', False) or not vs.path: + return + + archs = ('x86', 'x64') for arch in archs: - # Extract environment variables for subprocesses. - args = vs.SetupScript(arch) - args.extend(('&&', 'set')) - popen = subprocess.Popen( - args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - variables, _ = popen.communicate() - if popen.returncode != 0: - raise Exception('"%s" failed with error %d' % (args, popen.returncode)) - 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) - f.close() + env = _GetEnvironment(arch, vs) + env_block = NUL.join(encode(k) + '=' + encode(v) for k, v in env.items()) + NUL + NUL + with open(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb') as f: + f.write(env_block) + + +def _GetEnvironment(arch, vs): + """ + This function will run the VC environment setup script, retrieve variables, + and also the path on cl.exe. + It will then try to cache the values to disk, and on next run will try to + lookup the cache. The cache key is the path to the setup script (which is + embedded within each Visual Studio installed instance) + it's args. + Even after a cache hit we do some validation of the cached values, + since parts of the tool-set can be upgraded with in the installed lifecycle + so paths and version numbers may change. + + Args: + arch: {string} target architecture + vs: VisualStudioVersion + + Returns: {dict} the important environment variables VC need to run + + """ + args = vs.SetupScript(arch) + args.extend(('&&', 'set', '&&', 'where', 'cl.exe')) + args_slug = ''.join(args).encode('utf-8') + args_hash = hashlib.md5(args_slug).hexdigest() + cache_key = 'gyp-env-cache-' + args_hash + # The default value for %TEMP% will make all cache look ups to safely miss + cache_dir = os.environ.get('GYP_TEMP', gettempdir()) + cache_keyed_file = os.path.join(cache_dir, cache_key) + if os.path.exists(cache_keyed_file): + try: + with open(cache_keyed_file, 'rb') as f: + env = pickle.load(f) + except Exception as e: + DebugOutput(DEBUG_GENERAL, "Failed to load env pickle: %s" % e) + DebugOutput(DEBUG_GENERAL, "args_slug=%s" % args_slug) + DebugOutput(DEBUG_GENERAL, "cache_keyed_file=%s" % cache_keyed_file) + DebugOutput(DEBUG_GENERAL, traceback.format_exc()) + cl_path = env.get('GYP_CL_PATH', '') + if os.path.exists(cl_path): + return env + else: + # cache has become invalid (probably form a tool set update) + os.remove(cache_keyed_file) + start_time = time.clock() + # Extract environment variables for subprocesses. + std_out = subprocess.check_output(args, shell=True, stderr=subprocess.STDOUT).decode('utf-8') + end_time = time.clock() + DebugOutput(DEBUG_GENERAL, "vcvars %s time: %f" % (' '.join(args), end_time - start_time)) + env = _ExtractImportantEnvironment(std_out, arch) + try: + with open(cache_keyed_file, mode='wb') as f: + pickle.dump(env, f) + except Exception as e: + DebugOutput(DEBUG_GENERAL, "Failed to save env pickle: %s" % e) + DebugOutput(DEBUG_GENERAL, "args_slug=%s" % args_slug) + DebugOutput(DEBUG_GENERAL, "cache_keyed_file=%s" % cache_keyed_file) + DebugOutput(DEBUG_GENERAL, traceback.format_exc()) + return env - # Find cl.exe location for this architecture. - args = vs.SetupScript(arch) - args.extend(('&&', - 'for', '%i', 'in', '(cl.exe)', 'do', '@echo', 'LOC:%~$PATH:i')) - popen = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE) - output, _ = popen.communicate() - cl_paths[arch] = _ExtractCLPath(output) - return cl_paths def VerifyMissingSources(sources, build_dir, generator_flags, gyp_to_ninja): """Emulate behavior of msvs_error_on_missing_sources present in the msvs @@ -1078,21 +1007,22 @@ def VerifyMissingSources(sources, build_dir, generator_flags, gyp_to_ninja): if int(generator_flags.get('msvs_error_on_missing_sources', 0)): no_specials = filter(lambda x: '$' not in x, sources) relative = [os.path.join(build_dir, gyp_to_ninja(s)) for s in no_specials] - missing = filter(lambda x: not os.path.exists(x), relative) + missing = [x for x in relative if not os.path.exists(x)] if missing: # They'll look like out\Release\..\..\stuff\things.cc, so normalize the # 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() + msvs_version = GetVSVersion(generator_flags) + default_variables['MSVS_VERSION'] = msvs_version.short_name # To determine processor word size on Windows, in addition to checking # PROCESSOR_ARCHITECTURE (which reflects the word size of the current diff --git a/tools/gyp/pylib/gyp/MSVSSettings_test.py b/tools/gyp/gyp/unit_tests/MSVSSettings_test.py old mode 100755 new mode 100644 similarity index 81% rename from tools/gyp/pylib/gyp/MSVSSettings_test.py rename to tools/gyp/gyp/unit_tests/MSVSSettings_test.py index bf6ea6b802ff91..caf2e994bf5a36 --- a/tools/gyp/pylib/gyp/MSVSSettings_test.py +++ b/tools/gyp/gyp/unit_tests/MSVSSettings_test.py @@ -6,15 +6,18 @@ """Unit tests for the MSVSSettings.py file.""" -import StringIO import unittest -import gyp.MSVSSettings as MSVSSettings - +import gyp.MSVS.MSVSSettings as MSVSSettings +try: + # noinspection PyCompatibility + from cStringIO import StringIO +except ImportError: + from io import StringIO class TestSequenceFunctions(unittest.TestCase): def setUp(self): - self.stderr = StringIO.StringIO() + self.stderr = StringIO() def _ExpectedWarnings(self, expected): """Compares recorded lines to expected warnings.""" @@ -282,272 +285,282 @@ def testValidateMSVSSettings_settings(self): def testValidateMSBuildSettings_settings(self): """Tests that for invalid MSBuild settings.""" - MSVSSettings.ValidateMSBuildSettings( - {'ClCompile': { - 'AdditionalIncludeDirectories': 'folder1;folder2', - 'AdditionalOptions': ['string1', 'string2'], - 'AdditionalUsingDirectories': 'folder1;folder2', - 'AssemblerListingLocation': 'a_file_name', - 'AssemblerOutput': 'NoListing', - 'BasicRuntimeChecks': 'StackFrameRuntimeCheck', - 'BrowseInformation': 'false', - 'BrowseInformationFile': 'a_file_name', - 'BufferSecurityCheck': 'true', - 'BuildingInIDE': 'true', - 'CallingConvention': 'Cdecl', - 'CompileAs': 'CompileAsC', - 'CompileAsManaged': 'true', - 'CreateHotpatchableImage': 'true', - 'DebugInformationFormat': 'ProgramDatabase', - 'DisableLanguageExtensions': 'true', - 'DisableSpecificWarnings': 'string1;string2', - 'EnableEnhancedInstructionSet': 'StreamingSIMDExtensions', - 'EnableFiberSafeOptimizations': 'true', - 'EnablePREfast': 'true', - 'Enableprefast': 'bogus', - 'ErrorReporting': 'Prompt', - 'ExceptionHandling': 'SyncCThrow', - 'ExpandAttributedSource': 'true', - 'FavorSizeOrSpeed': 'Neither', - 'FloatingPointExceptions': 'true', - 'FloatingPointModel': 'Precise', - 'ForceConformanceInForLoopScope': 'true', - 'ForcedIncludeFiles': 'file1;file2', - 'ForcedUsingFiles': 'file1;file2', - 'FunctionLevelLinking': 'false', - 'GenerateXMLDocumentationFiles': 'true', - 'IgnoreStandardIncludePath': 'true', - 'InlineFunctionExpansion': 'OnlyExplicitInline', - 'IntrinsicFunctions': 'false', - 'MinimalRebuild': 'true', - 'MultiProcessorCompilation': 'true', - 'ObjectFileName': 'a_file_name', - 'OmitDefaultLibName': 'true', - 'OmitFramePointers': 'true', - 'OpenMPSupport': 'true', - 'Optimization': 'Disabled', - 'PrecompiledHeader': 'NotUsing', - 'PrecompiledHeaderFile': 'a_file_name', - 'PrecompiledHeaderOutputFile': 'a_file_name', - 'PreprocessKeepComments': 'true', - 'PreprocessorDefinitions': 'string1;string2', - 'PreprocessOutputPath': 'a string1', - 'PreprocessSuppressLineNumbers': 'false', - 'PreprocessToFile': 'false', - 'ProcessorNumber': '33', - 'ProgramDataBaseFileName': 'a_file_name', - 'RuntimeLibrary': 'MultiThreaded', - 'RuntimeTypeInfo': 'true', - 'ShowIncludes': 'true', - 'SmallerTypeCheck': 'true', - 'StringPooling': 'true', - 'StructMemberAlignment': '1Byte', - 'SuppressStartupBanner': 'true', - 'TrackerLogDirectory': 'a_folder', - 'TreatSpecificWarningsAsErrors': 'string1;string2', - 'TreatWarningAsError': 'true', - 'TreatWChar_tAsBuiltInType': 'true', - 'UndefineAllPreprocessorDefinitions': 'true', - 'UndefinePreprocessorDefinitions': 'string1;string2', - 'UseFullPaths': 'true', - 'UseUnicodeForAssemblerListing': 'true', - 'WarningLevel': 'TurnOffAllWarnings', - 'WholeProgramOptimization': 'true', - 'XMLDocumentationFileName': 'a_file_name', - 'ZZXYZ': 'bogus'}, - 'Link': { - 'AdditionalDependencies': 'file1;file2', - 'AdditionalLibraryDirectories': 'folder1;folder2', - 'AdditionalManifestDependencies': 'file1;file2', - 'AdditionalOptions': 'a string1', - 'AddModuleNamesToAssembly': 'file1;file2', - 'AllowIsolation': 'true', - 'AssemblyDebug': '', - 'AssemblyLinkResource': 'file1;file2', - 'BaseAddress': 'a string1', - 'BuildingInIDE': 'true', - 'CLRImageType': 'ForceIJWImage', - 'CLRSupportLastError': 'Enabled', - 'CLRThreadAttribute': 'MTAThreadingAttribute', - 'CLRUnmanagedCodeCheck': 'true', - 'CreateHotPatchableImage': 'X86Image', - 'DataExecutionPrevention': 'false', - 'DelayLoadDLLs': 'file1;file2', - 'DelaySign': 'true', - 'Driver': 'NotSet', - 'EmbedManagedResourceFile': 'file1;file2', - 'EnableCOMDATFolding': 'false', - 'EnableUAC': 'true', - 'EntryPointSymbol': 'a string1', - 'FixedBaseAddress': 'false', - 'ForceFileOutput': 'Enabled', - 'ForceSymbolReferences': 'file1;file2', - 'FunctionOrder': 'a_file_name', - 'GenerateDebugInformation': 'true', - 'GenerateMapFile': 'true', - 'HeapCommitSize': 'a string1', - 'HeapReserveSize': 'a string1', - 'IgnoreAllDefaultLibraries': 'true', - 'IgnoreEmbeddedIDL': 'true', - 'IgnoreSpecificDefaultLibraries': 'a_file_list', - 'ImageHasSafeExceptionHandlers': 'true', - 'ImportLibrary': 'a_file_name', - 'KeyContainer': 'a_file_name', - 'KeyFile': 'a_file_name', - 'LargeAddressAware': 'false', - 'LinkDLL': 'true', - 'LinkErrorReporting': 'SendErrorReport', - 'LinkStatus': 'true', - 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration', - 'ManifestFile': 'a_file_name', - 'MapExports': 'true', - 'MapFileName': 'a_file_name', - 'MergedIDLBaseFileName': 'a_file_name', - 'MergeSections': 'a string1', - 'MidlCommandFile': 'a_file_name', - 'MinimumRequiredVersion': 'a string1', - 'ModuleDefinitionFile': 'a_file_name', - 'MSDOSStubFileName': 'a_file_name', - 'NoEntryPoint': 'true', - 'OptimizeReferences': 'false', - 'OutputFile': 'a_file_name', - 'PerUserRedirection': 'true', - 'PreventDllBinding': 'true', - 'Profile': 'true', - 'ProfileGuidedDatabase': 'a_file_name', - 'ProgramDatabaseFile': 'a_file_name', - 'RandomizedBaseAddress': 'false', - 'RegisterOutput': 'true', - 'SectionAlignment': '33', - 'SetChecksum': 'true', - 'ShowProgress': 'LinkVerboseREF', - 'SpecifySectionAttributes': 'a string1', - 'StackCommitSize': 'a string1', - 'StackReserveSize': 'a string1', - 'StripPrivateSymbols': 'a_file_name', - 'SubSystem': 'Console', - 'SupportNobindOfDelayLoadedDLL': 'true', - 'SupportUnloadOfDelayLoadedDLL': 'true', - 'SuppressStartupBanner': 'true', - 'SwapRunFromCD': 'true', - 'SwapRunFromNET': 'true', - 'TargetMachine': 'MachineX86', - 'TerminalServerAware': 'false', - 'TrackerLogDirectory': 'a_folder', - 'TreatLinkerWarningAsErrors': 'true', - 'TurnOffAssemblyGeneration': 'true', - 'TypeLibraryFile': 'a_file_name', - 'TypeLibraryResourceID': '33', - 'UACExecutionLevel': 'AsInvoker', - 'UACUIAccess': 'true', - 'Version': 'a string1'}, - 'ResourceCompile': { - 'AdditionalIncludeDirectories': 'folder1;folder2', - 'AdditionalOptions': 'a string1', - 'Culture': '0x236', - 'IgnoreStandardIncludePath': 'true', - 'NullTerminateStrings': 'true', - 'PreprocessorDefinitions': 'string1;string2', - 'ResourceOutputFileName': 'a string1', - 'ShowProgress': 'true', - 'SuppressStartupBanner': 'true', - 'TrackerLogDirectory': 'a_folder', - 'UndefinePreprocessorDefinitions': 'string1;string2'}, - 'Midl': { - 'AdditionalIncludeDirectories': 'folder1;folder2', - 'AdditionalOptions': 'a string1', - 'ApplicationConfigurationMode': 'true', - 'ClientStubFile': 'a_file_name', - 'CPreprocessOptions': 'a string1', - 'DefaultCharType': 'Signed', - 'DllDataFileName': 'a_file_name', - 'EnableErrorChecks': 'EnableCustom', - 'ErrorCheckAllocations': 'true', - 'ErrorCheckBounds': 'true', - 'ErrorCheckEnumRange': 'true', - 'ErrorCheckRefPointers': 'true', - 'ErrorCheckStubData': 'true', - 'GenerateClientFiles': 'Stub', - 'GenerateServerFiles': 'None', - 'GenerateStublessProxies': 'true', - 'GenerateTypeLibrary': 'true', - 'HeaderFileName': 'a_file_name', - 'IgnoreStandardIncludePath': 'true', - 'InterfaceIdentifierFileName': 'a_file_name', - 'LocaleID': '33', - 'MkTypLibCompatible': 'true', - 'OutputDirectory': 'a string1', - 'PreprocessorDefinitions': 'string1;string2', - 'ProxyFileName': 'a_file_name', - 'RedirectOutputAndErrors': 'a_file_name', - 'ServerStubFile': 'a_file_name', - 'StructMemberAlignment': 'NotSet', - 'SuppressCompilerWarnings': 'true', - 'SuppressStartupBanner': 'true', - 'TargetEnvironment': 'Itanium', - 'TrackerLogDirectory': 'a_folder', - 'TypeLibFormat': 'NewFormat', - 'TypeLibraryName': 'a_file_name', - 'UndefinePreprocessorDefinitions': 'string1;string2', - 'ValidateAllParameters': 'true', - 'WarnAsError': 'true', - 'WarningLevel': '1'}, - 'Lib': { - 'AdditionalDependencies': 'file1;file2', - 'AdditionalLibraryDirectories': 'folder1;folder2', - 'AdditionalOptions': 'a string1', - 'DisplayLibrary': 'a string1', - 'ErrorReporting': 'PromptImmediately', - 'ExportNamedFunctions': 'string1;string2', - 'ForceSymbolReferences': 'a string1', - 'IgnoreAllDefaultLibraries': 'true', - 'IgnoreSpecificDefaultLibraries': 'file1;file2', - 'LinkTimeCodeGeneration': 'true', - 'MinimumRequiredVersion': 'a string1', - 'ModuleDefinitionFile': 'a_file_name', - 'Name': 'a_file_name', - 'OutputFile': 'a_file_name', - 'RemoveObjects': 'file1;file2', - 'SubSystem': 'Console', - 'SuppressStartupBanner': 'true', - 'TargetMachine': 'MachineX86i', - 'TrackerLogDirectory': 'a_folder', - 'TreatLibWarningAsErrors': 'true', - 'UseUnicodeResponseFiles': 'true', - 'Verbose': 'true'}, - 'Manifest': { - 'AdditionalManifestFiles': 'file1;file2', - 'AdditionalOptions': 'a string1', - 'AssemblyIdentity': 'a string1', - 'ComponentFileName': 'a_file_name', - 'EnableDPIAwareness': 'fal', - 'GenerateCatalogFiles': 'truel', - 'GenerateCategoryTags': 'true', - 'InputResourceManifests': 'a string1', - 'ManifestFromManagedAssembly': 'a_file_name', - 'notgood3': 'bogus', - 'OutputManifestFile': 'a_file_name', - 'OutputResourceManifests': 'a string1', - 'RegistrarScriptFile': 'a_file_name', - 'ReplacementsFile': 'a_file_name', - 'SuppressDependencyElement': 'true', - 'SuppressStartupBanner': 'true', - 'TrackerLogDirectory': 'a_folder', - 'TypeLibraryFile': 'a_file_name', - 'UpdateFileHashes': 'true', - 'UpdateFileHashesSearchPath': 'a_file_name', - 'VerboseOutput': 'true'}, - 'ProjectReference': { - 'LinkLibraryDependencies': 'true', - 'UseLibraryDependencyInputs': 'true'}, - 'ManifestResourceCompile': { - 'ResourceOutputFileName': 'a_file_name'}, - '': { - 'EmbedManifest': 'true', - 'GenerateManifest': 'true', - 'IgnoreImportLibrary': 'true', - 'LinkIncremental': 'false'}}, - self.stderr) + settings_fixture = { + 'ClCompile': { + 'AdditionalIncludeDirectories': 'folder1;folder2', + 'AdditionalOptions': ['string1', 'string2'], + 'AdditionalUsingDirectories': 'folder1;folder2', + 'AssemblerListingLocation': 'a_file_name', + 'AssemblerOutput': 'NoListing', + 'BasicRuntimeChecks': 'StackFrameRuntimeCheck', + 'BrowseInformation': 'false', + 'BrowseInformationFile': 'a_file_name', + 'BufferSecurityCheck': 'true', + 'BuildingInIDE': 'true', + 'CallingConvention': 'Cdecl', + 'CompileAs': 'CompileAsC', + 'CompileAsManaged': 'true', + 'CreateHotpatchableImage': 'true', + 'DebugInformationFormat': 'ProgramDatabase', + 'DisableLanguageExtensions': 'true', + 'DisableSpecificWarnings': 'string1;string2', + 'EnableEnhancedInstructionSet': 'StreamingSIMDExtensions', + 'EnableFiberSafeOptimizations': 'true', + 'EnablePREfast': 'true', + 'Enableprefast': 'bogus', + 'ErrorReporting': 'Prompt', + 'ExceptionHandling': 'SyncCThrow', + 'ExpandAttributedSource': 'true', + 'FavorSizeOrSpeed': 'Neither', + 'FloatingPointExceptions': 'true', + 'FloatingPointModel': 'Precise', + 'ForceConformanceInForLoopScope': 'true', + 'ForcedIncludeFiles': 'file1;file2', + 'ForcedUsingFiles': 'file1;file2', + 'FunctionLevelLinking': 'false', + 'GenerateXMLDocumentationFiles': 'true', + 'IgnoreStandardIncludePath': 'true', + 'InlineFunctionExpansion': 'OnlyExplicitInline', + 'IntrinsicFunctions': 'false', + 'MinimalRebuild': 'true', + 'MultiProcessorCompilation': 'true', + 'ObjectFileName': 'a_file_name', + 'OmitDefaultLibName': 'true', + 'OmitFramePointers': 'true', + 'OpenMPSupport': 'true', + 'Optimization': 'Disabled', + 'PrecompiledHeader': 'NotUsing', + 'PrecompiledHeaderFile': 'a_file_name', + 'PrecompiledHeaderOutputFile': 'a_file_name', + 'PreprocessKeepComments': 'true', + 'PreprocessorDefinitions': 'string1;string2', + 'PreprocessOutputPath': 'a string1', + 'PreprocessSuppressLineNumbers': 'false', + 'PreprocessToFile': 'false', + 'ProcessorNumber': '33', + 'ProgramDataBaseFileName': 'a_file_name', + 'RuntimeLibrary': 'MultiThreaded', + 'RuntimeTypeInfo': 'true', + 'ShowIncludes': 'true', + 'SmallerTypeCheck': 'true', + 'StringPooling': 'true', + 'StructMemberAlignment': '1Byte', + 'SuppressStartupBanner': 'true', + 'TrackerLogDirectory': 'a_folder', + 'TreatSpecificWarningsAsErrors': 'string1;string2', + 'TreatWarningAsError': 'true', + 'TreatWChar_tAsBuiltInType': 'true', + 'UndefineAllPreprocessorDefinitions': 'true', + 'UndefinePreprocessorDefinitions': 'string1;string2', + 'UseFullPaths': 'true', + 'UseUnicodeForAssemblerListing': 'true', + 'WarningLevel': 'TurnOffAllWarnings', + 'WholeProgramOptimization': 'true', + 'XMLDocumentationFileName': 'a_file_name', + 'ZZXYZ': 'bogus' + }, + 'Link': { + 'AdditionalDependencies': 'file1;file2', + 'AdditionalLibraryDirectories': 'folder1;folder2', + 'AdditionalManifestDependencies': 'file1;file2', + 'AdditionalOptions': 'a string1', + 'AddModuleNamesToAssembly': 'file1;file2', + 'AllowIsolation': 'true', + 'AssemblyDebug': '', + 'AssemblyLinkResource': 'file1;file2', + 'BaseAddress': 'a string1', + 'BuildingInIDE': 'true', + 'CLRImageType': 'ForceIJWImage', + 'CLRSupportLastError': 'Enabled', + 'CLRThreadAttribute': 'MTAThreadingAttribute', + 'CLRUnmanagedCodeCheck': 'true', + 'CreateHotPatchableImage': 'X86Image', + 'DataExecutionPrevention': 'false', + 'DelayLoadDLLs': 'file1;file2', + 'DelaySign': 'true', + 'Driver': 'NotSet', + 'EmbedManagedResourceFile': 'file1;file2', + 'EnableCOMDATFolding': 'false', + 'EnableUAC': 'true', + 'EntryPointSymbol': 'a string1', + 'FixedBaseAddress': 'false', + 'ForceFileOutput': 'Enabled', + 'ForceSymbolReferences': 'file1;file2', + 'FunctionOrder': 'a_file_name', + 'GenerateDebugInformation': 'true', + 'GenerateMapFile': 'true', + 'HeapCommitSize': 'a string1', + 'HeapReserveSize': 'a string1', + 'IgnoreAllDefaultLibraries': 'true', + 'IgnoreEmbeddedIDL': 'true', + 'IgnoreSpecificDefaultLibraries': 'a_file_list', + 'ImageHasSafeExceptionHandlers': 'true', + 'ImportLibrary': 'a_file_name', + 'KeyContainer': 'a_file_name', + 'KeyFile': 'a_file_name', + 'LargeAddressAware': 'false', + 'LinkDLL': 'true', + 'LinkErrorReporting': 'SendErrorReport', + 'LinkStatus': 'true', + 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration', + 'ManifestFile': 'a_file_name', + 'MapExports': 'true', + 'MapFileName': 'a_file_name', + 'MergedIDLBaseFileName': 'a_file_name', + 'MergeSections': 'a string1', + 'MidlCommandFile': 'a_file_name', + 'MinimumRequiredVersion': 'a string1', + 'ModuleDefinitionFile': 'a_file_name', + 'MSDOSStubFileName': 'a_file_name', + 'NoEntryPoint': 'true', + 'OptimizeReferences': 'false', + 'OutputFile': 'a_file_name', + 'PerUserRedirection': 'true', + 'PreventDllBinding': 'true', + 'Profile': 'true', + 'ProfileGuidedDatabase': 'a_file_name', + 'ProgramDatabaseFile': 'a_file_name', + 'RandomizedBaseAddress': 'false', + 'RegisterOutput': 'true', + 'SectionAlignment': '33', + 'SetChecksum': 'true', + 'ShowProgress': 'LinkVerboseREF', + 'SpecifySectionAttributes': 'a string1', + 'StackCommitSize': 'a string1', + 'StackReserveSize': 'a string1', + 'StripPrivateSymbols': 'a_file_name', + 'SubSystem': 'Console', + 'SupportNobindOfDelayLoadedDLL': 'true', + 'SupportUnloadOfDelayLoadedDLL': 'true', + 'SuppressStartupBanner': 'true', + 'SwapRunFromCD': 'true', + 'SwapRunFromNET': 'true', + 'TargetMachine': 'MachineX86', + 'TerminalServerAware': 'false', + 'TrackerLogDirectory': 'a_folder', + 'TreatLinkerWarningAsErrors': 'true', + 'TurnOffAssemblyGeneration': 'true', + 'TypeLibraryFile': 'a_file_name', + 'TypeLibraryResourceID': '33', + 'UACExecutionLevel': 'AsInvoker', + 'UACUIAccess': 'true', + 'Version': 'a string1' + }, + 'ResourceCompile': { + 'AdditionalIncludeDirectories': 'folder1;folder2', + 'AdditionalOptions': 'a string1', + 'Culture': '0x236', + 'IgnoreStandardIncludePath': 'true', + 'NullTerminateStrings': 'true', + 'PreprocessorDefinitions': 'string1;string2', + 'ResourceOutputFileName': 'a string1', + 'ShowProgress': 'true', + 'SuppressStartupBanner': 'true', + 'TrackerLogDirectory': 'a_folder', + 'UndefinePreprocessorDefinitions': 'string1;string2' + }, + 'Midl': { + 'AdditionalIncludeDirectories': 'folder1;folder2', + 'AdditionalOptions': 'a string1', + 'ApplicationConfigurationMode': 'true', + 'ClientStubFile': 'a_file_name', + 'CPreprocessOptions': 'a string1', + 'DefaultCharType': 'Signed', + 'DllDataFileName': 'a_file_name', + 'EnableErrorChecks': 'EnableCustom', + 'ErrorCheckAllocations': 'true', + 'ErrorCheckBounds': 'true', + 'ErrorCheckEnumRange': 'true', + 'ErrorCheckRefPointers': 'true', + 'ErrorCheckStubData': 'true', + 'GenerateClientFiles': 'Stub', + 'GenerateServerFiles': 'None', + 'GenerateStublessProxies': 'true', + 'GenerateTypeLibrary': 'true', + 'HeaderFileName': 'a_file_name', + 'IgnoreStandardIncludePath': 'true', + 'InterfaceIdentifierFileName': 'a_file_name', + 'LocaleID': '33', + 'MkTypLibCompatible': 'true', + 'OutputDirectory': 'a string1', + 'PreprocessorDefinitions': 'string1;string2', + 'ProxyFileName': 'a_file_name', + 'RedirectOutputAndErrors': 'a_file_name', + 'ServerStubFile': 'a_file_name', + 'StructMemberAlignment': 'NotSet', + 'SuppressCompilerWarnings': 'true', + 'SuppressStartupBanner': 'true', + 'TargetEnvironment': 'Itanium', + 'TrackerLogDirectory': 'a_folder', + 'TypeLibFormat': 'NewFormat', + 'TypeLibraryName': 'a_file_name', + 'UndefinePreprocessorDefinitions': 'string1;string2', + 'ValidateAllParameters': 'true', + 'WarnAsError': 'true', + 'WarningLevel': '1' + }, + 'Lib': { + 'AdditionalDependencies': 'file1;file2', + 'AdditionalLibraryDirectories': 'folder1;folder2', + 'AdditionalOptions': 'a string1', + 'DisplayLibrary': 'a string1', + 'ErrorReporting': 'PromptImmediately', + 'ExportNamedFunctions': 'string1;string2', + 'ForceSymbolReferences': 'a string1', + 'IgnoreAllDefaultLibraries': 'true', + 'IgnoreSpecificDefaultLibraries': 'file1;file2', + 'LinkTimeCodeGeneration': 'true', + 'MinimumRequiredVersion': 'a string1', + 'ModuleDefinitionFile': 'a_file_name', + 'Name': 'a_file_name', + 'OutputFile': 'a_file_name', + 'RemoveObjects': 'file1;file2', + 'SubSystem': 'Console', + 'SuppressStartupBanner': 'true', + 'TargetMachine': 'MachineX86i', + 'TrackerLogDirectory': 'a_folder', + 'TreatLibWarningAsErrors': 'true', + 'UseUnicodeResponseFiles': 'true', + 'Verbose': 'true' + }, + 'Manifest': { + 'AdditionalManifestFiles': 'file1;file2', + 'AdditionalOptions': 'a string1', + 'AssemblyIdentity': 'a string1', + 'ComponentFileName': 'a_file_name', + 'EnableDPIAwareness': 'fal', + 'GenerateCatalogFiles': 'truel', + 'GenerateCategoryTags': 'true', + 'InputResourceManifests': 'a string1', + 'ManifestFromManagedAssembly': 'a_file_name', + 'notgood3': 'bogus', + 'OutputManifestFile': 'a_file_name', + 'OutputResourceManifests': 'a string1', + 'RegistrarScriptFile': 'a_file_name', + 'ReplacementsFile': 'a_file_name', + 'SuppressDependencyElement': 'true', + 'SuppressStartupBanner': 'true', + 'TrackerLogDirectory': 'a_folder', + 'TypeLibraryFile': 'a_file_name', + 'UpdateFileHashes': 'true', + 'UpdateFileHashesSearchPath': 'a_file_name', + 'VerboseOutput': 'true' + }, + 'ProjectReference': { + 'LinkLibraryDependencies': 'true', + 'UseLibraryDependencyInputs': 'true' + }, + 'ManifestResourceCompile': { + 'ResourceOutputFileName': 'a_file_name' + }, + '': { + 'EmbedManifest': 'true', + 'GenerateManifest': 'true', + 'IgnoreImportLibrary': 'true', + 'LinkIncremental': 'false' + } + } + MSVSSettings.ValidateMSBuildSettings(settings_fixture, self.stderr) self._ExpectedWarnings([ 'Warning: unrecognized setting ClCompile/Enableprefast', 'Warning: unrecognized setting ClCompile/ZZXYZ', @@ -628,9 +641,7 @@ def testConvertToMSBuildSettings_warnings(self): 'ResourceCompile': { # Custom 'Culture': '0x03eb'}} - actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings( - msvs_settings, - self.stderr) + actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(msvs_settings, self.stderr) self.assertEqual(expected_msbuild_settings, actual_msbuild_settings) self._ExpectedWarnings([ 'Warning: while converting VCCLCompilerTool/BasicRuntimeChecks to ' diff --git a/tools/gyp/gyp/unit_tests/NinjaWriter_test.py b/tools/gyp/gyp/unit_tests/NinjaWriter_test.py new file mode 100644 index 00000000000000..e00141117180f5 --- /dev/null +++ b/tools/gyp/gyp/unit_tests/NinjaWriter_test.py @@ -0,0 +1,39 @@ +#!/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. + +""" Unit tests for the ninja.py file. """ + +import unittest +import sys + +import gyp.NinjaWriter + + +class TestPrefixesAndSuffixes(unittest.TestCase): + spec = {'target_name': 'wee', 'type': 'executable', 'toolset': 'target', 'configurations': {'gu': {}, 'ga': {}}} + def setUp(self): + self.win_writer = gyp.NinjaWriter.NinjaWriter('foo', 'wee', '.', '.', 'build.ninja', '.', 'build.ninja', 'win', self.spec, {'msvs_version': '2019'}, 'gu', '.') + self.linux_writer = gyp.NinjaWriter.NinjaWriter('foo', 'wee', '.', '.', 'build.ninja', '.', 'build.ninja', 'linux', self.spec, {'msvs_version': '2019'}, 'ga', '.') + + def test_BinaryNamesWindows(self): + # These cannot run on non-Windows as they require a VS installation to + # correctly handle variable expansion. + if not sys.platform.startswith('win'): + self.skipTest('can only run on windows') + self.assertTrue(self.win_writer.ComputeOutputFileName(self.spec, 'executable').endswith('.exe')) + self.assertTrue(self.win_writer.ComputeOutputFileName(self.spec, 'shared_library').endswith('.dll')) + self.assertTrue(self.win_writer.ComputeOutputFileName(self.spec, 'static_library').endswith('.lib')) + + def test_BinaryNamesLinux(self): + self.assertTrue('.' not in self.linux_writer.ComputeOutputFileName(self.spec, 'executable')) + self.assertTrue(self.linux_writer.ComputeOutputFileName(self.spec, 'shared_library').startswith('lib')) + self.assertTrue(self.linux_writer.ComputeOutputFileName(self.spec, 'static_library').startswith('lib')) + self.assertTrue(self.linux_writer.ComputeOutputFileName(self.spec, 'shared_library').endswith('.so')) + self.assertTrue(self.linux_writer.ComputeOutputFileName(self.spec, 'static_library').endswith('.a')) + + +if __name__ == '__main__': + unittest.main() diff --git a/tools/gyp/gyp/unit_tests/__init__.py b/tools/gyp/gyp/unit_tests/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/pylib/gyp/common_test.py b/tools/gyp/gyp/unit_tests/common_test.py old mode 100755 new mode 100644 similarity index 97% rename from tools/gyp/pylib/gyp/common_test.py rename to tools/gyp/gyp/unit_tests/common_test.py index ad6f9a1438f30f..0b8ada3dc3c0af --- a/tools/gyp/pylib/gyp/common_test.py +++ b/tools/gyp/gyp/unit_tests/common_test.py @@ -63,6 +63,7 @@ def test_platform_default(self): self.assertFlavor('solaris', 'sunos' , {}); self.assertFlavor('linux' , 'linux2' , {}); self.assertFlavor('linux' , 'linux3' , {}); + self.assertFlavor('linux' , 'linux' , {}); def test_param(self): self.assertFlavor('foobar', 'linux2' , {'flavor': 'foobar'}) diff --git a/tools/gyp/pylib/gyp/easy_xml_test.py b/tools/gyp/gyp/unit_tests/easy_xml_test.py old mode 100755 new mode 100644 similarity index 98% rename from tools/gyp/pylib/gyp/easy_xml_test.py rename to tools/gyp/gyp/unit_tests/easy_xml_test.py index df64354982c01d..79c5a61ff2255f --- a/tools/gyp/pylib/gyp/easy_xml_test.py +++ b/tools/gyp/gyp/unit_tests/easy_xml_test.py @@ -8,13 +8,13 @@ import gyp.easy_xml as easy_xml import unittest -import StringIO +from io import StringIO class TestSequenceFunctions(unittest.TestCase): def setUp(self): - self.stderr = StringIO.StringIO() + self.stderr = StringIO() def test_EasyXml_simple(self): self.assertEqual( diff --git a/tools/gyp/pylib/gyp/generator/msvs_test.py b/tools/gyp/gyp/unit_tests/generator_msvs_test.py old mode 100755 new mode 100644 similarity index 94% rename from tools/gyp/pylib/gyp/generator/msvs_test.py rename to tools/gyp/gyp/unit_tests/generator_msvs_test.py index c0b021df502bfa..fd0fcd0804ebe9 --- a/tools/gyp/pylib/gyp/generator/msvs_test.py +++ b/tools/gyp/gyp/unit_tests/generator_msvs_test.py @@ -7,13 +7,13 @@ import gyp.generator.msvs as msvs import unittest -import StringIO +from io import StringIO class TestSequenceFunctions(unittest.TestCase): def setUp(self): - self.stderr = StringIO.StringIO() + self.stderr = StringIO() def test_GetLibraries(self): self.assertEqual( diff --git a/tools/gyp/pylib/gyp/generator/xcode_test.py b/tools/gyp/gyp/unit_tests/generator_xcode_test.py similarity index 100% rename from tools/gyp/pylib/gyp/generator/xcode_test.py rename to tools/gyp/gyp/unit_tests/generator_xcode_test.py diff --git a/tools/gyp/pylib/gyp/input_test.py b/tools/gyp/gyp/unit_tests/input_test.py old mode 100755 new mode 100644 similarity index 81% rename from tools/gyp/pylib/gyp/input_test.py rename to tools/gyp/gyp/unit_tests/input_test.py index 4234fbb8302eb9..7b7216d7f43900 --- a/tools/gyp/pylib/gyp/input_test.py +++ b/tools/gyp/gyp/unit_tests/input_test.py @@ -8,7 +8,6 @@ import gyp.input import unittest -import sys class TestFindCycles(unittest.TestCase): @@ -22,38 +21,38 @@ def _create_dependency(self, dependent, dependency): dependency.dependents.append(dependent) def test_no_cycle_empty_graph(self): - for label, node in self.nodes.iteritems(): - self.assertEquals([], node.FindCycles()) + for label, node in self.nodes.items(): + self.assertEqual([], node.FindCycles()) def test_no_cycle_line(self): self._create_dependency(self.nodes['a'], self.nodes['b']) self._create_dependency(self.nodes['b'], self.nodes['c']) self._create_dependency(self.nodes['c'], self.nodes['d']) - for label, node in self.nodes.iteritems(): - self.assertEquals([], node.FindCycles()) + for label, node in self.nodes.items(): + self.assertEqual([], node.FindCycles()) def test_no_cycle_dag(self): self._create_dependency(self.nodes['a'], self.nodes['b']) self._create_dependency(self.nodes['a'], self.nodes['c']) self._create_dependency(self.nodes['b'], self.nodes['c']) - for label, node in self.nodes.iteritems(): - self.assertEquals([], node.FindCycles()) + for label, node in self.nodes.items(): + self.assertEqual([], node.FindCycles()) def test_cycle_self_reference(self): self._create_dependency(self.nodes['a'], self.nodes['a']) - self.assertEquals([[self.nodes['a'], self.nodes['a']]], + self.assertEqual([[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.assertEqual([[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.assertEqual([[self.nodes['b'], self.nodes['a'], self.nodes['b']]], self.nodes['b'].FindCycles()) def test_two_cycles(self): @@ -68,7 +67,7 @@ def test_two_cycles(self): [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.assertEquals(2, len(cycles)) + self.assertEqual(2, len(cycles)) def test_big_cycle(self): self._create_dependency(self.nodes['a'], self.nodes['b']) @@ -77,7 +76,7 @@ def test_big_cycle(self): self._create_dependency(self.nodes['d'], self.nodes['e']) self._create_dependency(self.nodes['e'], self.nodes['a']) - self.assertEquals([[self.nodes['a'], + self.assertEqual([[self.nodes['a'], self.nodes['b'], self.nodes['c'], self.nodes['d'], diff --git a/tools/gyp/pylib/gyp/xcode_emulation.py b/tools/gyp/gyp/xcode_emulation.py similarity index 95% rename from tools/gyp/pylib/gyp/xcode_emulation.py rename to tools/gyp/gyp/xcode_emulation.py index 9481423228ab47..d284c39636bd45 100644 --- a/tools/gyp/pylib/gyp/xcode_emulation.py +++ b/tools/gyp/gyp/xcode_emulation.py @@ -7,6 +7,8 @@ other build systems, such as make and ninja. """ +from __future__ import print_function + import copy import gyp.common import os @@ -15,7 +17,6 @@ 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 @@ -73,7 +74,8 @@ def _ExpandArchs(self, archs, sdkroot): if arch not in expanded_archs: expanded_archs.append(arch) except KeyError as e: - print 'Warning: Ignoring unsupported variable "%s".' % variable + print('Warning: Ignoring unsupported variable "%s".' % variable) + print(e) elif arch not in expanded_archs: expanded_archs.append(arch) return expanded_archs @@ -171,7 +173,7 @@ def __init__(self, spec): # the same for all configs are implicitly per-target settings. self.xcode_settings = {} configs = spec['configurations'] - for configname, config in configs.iteritems(): + for configname, config in configs.items(): self.xcode_settings[configname] = config.get('xcode_settings', {}) self._ConvertConditionalKeys(configname) if self.xcode_settings[configname].get('IPHONEOS_DEPLOYMENT_TARGET', @@ -197,8 +199,7 @@ def _ConvertConditionalKeys(self, configname): new_key = key.split("[")[0] settings[new_key] = settings[key] else: - print 'Warning: Conditional keys not implemented, ignoring:', \ - ' '.join(conditional_keys) + print('Warning: Conditional keys not implemented, ignoring:', ' '.join(conditional_keys)) del settings[key] def _Settings(self): @@ -216,12 +217,11 @@ def _Appendf(self, lst, test_key, format_str, default=None): def _WarnUnimplemented(self, test_key): if test_key in self._Settings(): - print 'Warning: Ignoring not yet implemented key "%s".' % test_key + 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) + format = self.xcode_settings[configname].get('INFOPLIST_OUTPUT_FORMAT', default) return format == "binary" def IsIosFramework(self): @@ -421,8 +421,7 @@ def _GetBundleBinaryPath(self): """Returns the name of the bundle binary of by this target. E.g. Chromium.app/Contents/MacOS/Chromium. Only valid for bundles.""" assert self._IsBundle() - return os.path.join(self.GetBundleExecutableFolderPath(), \ - self.GetExecutableName()) + return os.path.join(self.GetBundleExecutableFolderPath(), self.GetExecutableName()) def _GetStandaloneExecutableSuffix(self): if 'product_extension' in self.spec: @@ -495,7 +494,7 @@ def _GetSdkVersionInfoItem(self, sdk, infoitem): # Since the CLT has no SDK paths anyway, returning None is the # most sensible route and should still do the right thing. try: - return GetStdoutQuiet(['xcrun', '--sdk', sdk, infoitem]) + return GetStdout(['xcrun', '--sdk', sdk, infoitem]) except: pass @@ -507,8 +506,7 @@ def _SdkRoot(self, configname): def _XcodePlatformPath(self, configname=None): sdk_root = self._SdkRoot(configname) if sdk_root not in XcodeSettings._platform_path_cache: - platform_path = self._GetSdkVersionInfoItem(sdk_root, - '--show-sdk-platform-path') + platform_path = self._GetSdkVersionInfoItem(sdk_root, '--show-sdk-platform-path') XcodeSettings._platform_path_cache[sdk_root] = platform_path return XcodeSettings._platform_path_cache[sdk_root] @@ -645,10 +643,9 @@ def GetCflags(self, configname, arch=None): cflags += self._Settings().get('WARNING_CFLAGS', []) - if self._IsXCTest(): - platform_root = self._XcodePlatformPath(configname) - if platform_root: - cflags.append('-F' + platform_root + '/Developer/Library/Frameworks/') + platform_root = self._XcodePlatformPath(configname) + if platform_root and self._IsXCTest(): + cflags.append('-F' + platform_root + '/Developer/Library/Frameworks/') if sdk_root: framework_root = sdk_root @@ -914,11 +911,10 @@ def GetLdflags(self, configname, product_dir, gyp_to_build_path, arch=None): for directory in framework_dirs: ldflags.append('-F' + directory.replace('$(SDKROOT)', sdk_root)) - if self._IsXCTest(): - platform_root = self._XcodePlatformPath(configname) - if sdk_root and platform_root: - ldflags.append('-F' + platform_root + '/Developer/Library/Frameworks/') - ldflags.append('-framework XCTest') + platform_root = self._XcodePlatformPath(configname) + if sdk_root and platform_root and self._IsXCTest(): + ldflags.append('-F' + platform_root + '/Developer/Library/Frameworks/') + ldflags.append('-framework XCTest') is_extension = self._IsIosAppExtension() or self._IsIosWatchKitExtension() if sdk_root and is_extension: @@ -965,7 +961,7 @@ def GetPerTargetSettings(self): result = dict(self.xcode_settings[configname]) first_pass = False else: - for key, value in self.xcode_settings[configname].iteritems(): + for key, value in self.xcode_settings[configname].items(): if key not in result: continue elif result[key] != value: @@ -1058,7 +1054,7 @@ def _GetTargetPostbuilds(self, configname, output, output_binary, self._GetDebugInfoPostbuilds(configname, output, output_binary, quiet) + self._GetStripPostbuilds(configname, output_binary, quiet)) - def _GetIOSPostbuilds(self, configname, output_binary): + def _GetIOSPostbuilds(self, configname): """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.""" @@ -1074,7 +1070,7 @@ def _GetIOSPostbuilds(self, configname, output_binary): # Xcode expects XCTests to be copied into the TEST_HOST dir. if self._IsXCTest(): source = os.path.join("${BUILT_PRODUCTS_DIR}", product_name) - test_host = os.path.dirname(settings.get('TEST_HOST')); + test_host = os.path.dirname(settings.get('TEST_HOST')) xctest_destination = os.path.join(test_host, 'PlugIns', product_name) postbuilds.extend(['ditto %s %s' % (source, xctest_destination)]) @@ -1086,12 +1082,12 @@ def _GetIOSPostbuilds(self, configname, output_binary): 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))) + print('Warning: Some codesign keys not implemented, ignoring: %s' % ( + ', '.join(sorted(unimpl)))) if self._IsXCTest(): # For device xctests, Xcode copies two extra frameworks into $TEST_HOST. - test_host = os.path.dirname(settings.get('TEST_HOST')); + test_host = os.path.dirname(settings.get('TEST_HOST')) frameworks_dir = os.path.join(test_host, 'Frameworks') platform_root = self._XcodePlatformPath(configname) frameworks = \ @@ -1141,13 +1137,15 @@ def _GetIOSCodeSignIdentityKey(self, settings): 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|.""" + def AddImplicitPostbuilds(self, configname, output, output_binary, postbuilds=None, quiet=False): + """ + Returns a list of shell commands that should run before and after |postbuilds|. + """ assert output_binary is not None + if postbuilds is None: + postbuilds = [] pre = self._GetTargetPostbuilds(configname, output, output_binary, quiet) - post = self._GetIOSPostbuilds(configname, output_binary) + post = self._GetIOSPostbuilds(configname) return pre + postbuilds + post def _AdjustLibrary(self, library, config_name=None): @@ -1394,7 +1392,7 @@ def XcodeVersion(): if XCODE_VERSION_CACHE: return XCODE_VERSION_CACHE try: - version_list = GetStdoutQuiet(['xcodebuild', '-version']).splitlines() + 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 @@ -1405,16 +1403,16 @@ def XcodeVersion(): except: version = CLTVersion() if version: - version = re.match(r'(\d+\.\d+\.?\d*)', version).groups()[0] + version = re.search(r'^(\d{1,2}\.\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) + # Be careful to convert "4.2" to "0420" and "10.0" to "1000": + version = format(''.join((version.split()[-1].split('.') + ['0', '0'])[:3]), + '>04s') if build: build = build.split()[-1] XCODE_VERSION_CACHE = (version, build) @@ -1444,25 +1442,17 @@ def CLTVersion(): continue -def GetStdoutQuiet(cmdlist): - """Returns the content of standard output returned by invoking |cmdlist|. - Ignores the stderr. - Raises |GypError| if the command return with a non-zero return code.""" - job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - out = job.communicate()[0] - if job.returncode != 0: - raise GypError('Error %d running %s' % (job.returncode, cmdlist[0])) - return out.rstrip('\n') - - -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] +def GetStdout(cmdlist, with_stderr=False): + """ + 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, stderr=subprocess.PIPE) + out, err = job.communicate() if job.returncode != 0: - sys.stderr.write(out + '\n') + if with_stderr: + print(out, file=sys.stderr) + print(err, file=sys.stderr) raise GypError('Error %d running %s' % (job.returncode, cmdlist[0])) return out.rstrip('\n') @@ -1541,24 +1531,19 @@ def GetMacBundleResources(product_dir, xcode_settings, resources): def GetMacInfoPlist(product_dir, xcode_settings, gyp_path_to_build_path): - """Returns (info_plist, dest_plist, defines, extra_env), where: - * |info_plist| is the source plist path, relative to the - build directory, - * |dest_plist| is the destination plist path, relative to the - build directory, - * |defines| is a list of preprocessor defines (empty if the plist - shouldn't be preprocessed, - * |extra_env| is a dict of env variables that should be exported when - invoking |mac_tool copy-info-plist|. + """ + Returns (info_plist, dest_plist, defines, extra_env), where: + * |info_plist| is the source plist path, relative to the build directory, + * |dest_plist| is the destination plist path, relative to the build directory, + * |defines| is a list of preprocessor defines (empty if the plist shouldn't be preprocessed, + * |extra_env| is a dict of env variables that should be exported when invoking |mac_tool copy-info-plist|. Only call this for mac bundle targets. Args: - product_dir: Path to the directory containing the output bundle, - relative to the build directory. + product_dir: Path to the directory containing the output bundle, relative to the build directory. xcode_settings: The XcodeSettings of the current target. - gyp_to_build_path: A function that converts paths relative to the - current gyp file to paths relative to the build direcotry. + gyp_path_to_build_path: A function that converts paths relative to the current gyp file to paths relative to the build direcotry. """ info_plist = xcode_settings.GetPerTargetSetting('INFOPLIST_FILE') if not info_plist: @@ -1676,8 +1661,6 @@ def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, sdk_root = xcode_settings._SdkRoot(configuration) if not sdk_root: sdk_root = xcode_settings._XcodeSdkPath('') - if sdk_root is None: - sdk_root = '' env['SDKROOT'] = sdk_root if not additional_settings: @@ -1734,7 +1717,7 @@ def _TopologicallySortedEnvVarKeys(env): # Since environment variables can refer to other variables, the evaluation # order is important. Below is the logic to compute the dependency graph # and sort it. - regex = re.compile(r'\$\{([a-zA-Z0-9\-_]+)\}') + regex = re.compile(r'\${([a-zA-Z0-9\-_]+)\}') def GetEdges(node): # Use a definition of edges such that user_of_variable -> used_varible. # This happens to be easier in this case, since a variable's @@ -1753,7 +1736,7 @@ def GetEdges(node): order = gyp.common.TopologicallySorted(env.keys(), GetEdges) order.reverse() return order - except gyp.common.CycleError, e: + except gyp.common.CycleError as e: raise GypError( 'Xcode environment variables are cyclically dependent: ' + str(e.nodes)) @@ -1790,10 +1773,11 @@ def _HasIOSTarget(targets): 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(): + for target_dict in targets.values(): toolset = target_dict['toolset'] configs = target_dict['configurations'] - for config_name, simulator_config_dict in dict(configs).iteritems(): + + for config_name, simulator_config_dict in dict(configs).items(): iphoneos_config_dict = copy.deepcopy(simulator_config_dict) configs[config_name + '-iphoneos'] = iphoneos_config_dict configs[config_name + '-iphonesimulator'] = simulator_config_dict diff --git a/tools/gyp/gyp_main.py b/tools/gyp/gyp_main.py index 25a6eba94aae7d..b08f9a9b623613 100755 --- a/tools/gyp/gyp_main.py +++ b/tools/gyp/gyp_main.py @@ -1,15 +1,5 @@ #!/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 os import sys - -# 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__': diff --git a/tools/gyp/gyptest.py b/tools/gyp/gyptest.py index 9930e78c7b0f1c..2036effe43b939 100755 --- a/tools/gyp/gyptest.py +++ b/tools/gyp/gyptest.py @@ -1,20 +1,22 @@ #!/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. +# Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. """gyptest.py -- test runner for GYP tests.""" from __future__ import print_function +# noinspection PyCompatibility import argparse -import math import os import platform import subprocess import sys import time +from glob import glob +gyp_root = os.path.abspath(os.path.dirname(__file__)) +os.environ['PYTHONPATH'] = os.pathsep.join([os.path.join(gyp_root, 'gyp'), os.path.join(gyp_root, 'testlib'), os.environ.get('PYTHONPATH', '')]) def is_test_name(f): return f.startswith('gyptest') and f.endswith('.py') @@ -23,34 +25,22 @@ def is_test_name(f): def find_all_gyptest_files(directory): result = [] for root, dirs, files in os.walk(directory): - result.extend([ os.path.join(root, f) for f in files if is_test_name(f) ]) + result.extend([os.path.join(root, f) for f in files if is_test_name(f)]) result.sort() return result -def main(argv=None): - if argv is None: - argv = sys.argv - - parser = argparse.ArgumentParser() - parser.add_argument("-a", "--all", action="store_true", - help="run all tests") - parser.add_argument("-C", "--chdir", action="store", - help="change to directory") - parser.add_argument("-f", "--format", action="store", default='', - help="run tests with the specified formats") - parser.add_argument("-G", '--gyp_option', action="append", default=[], - help="Add -G options to the gyp command line") - parser.add_argument("-l", "--list", action="store_true", - help="list available tests and exit") - parser.add_argument("-n", "--no-exec", action="store_true", - help="no execute, just print the command line") - parser.add_argument("--path", action="append", default=[], - help="additional $PATH directory") - parser.add_argument("-q", "--quiet", action="store_true", - help="quiet, don't print anything unless there are failures") - parser.add_argument("-v", "--verbose", action="store_true", - help="print configuration info and test results.") +def main(argv): + parser = argparse.ArgumentParser(fromfile_prefix_chars='@') + parser.add_argument("-a", "--all", action="store_true", help="run all tests") + parser.add_argument("-C", "--chdir", action="store", help="change to directory") + parser.add_argument("-f", "--format", action="store", default='', help="run tests with the specified formats") + parser.add_argument("-G", '--gyp_option', action="append", default=[], help="Add -G options to the gyp command line") + parser.add_argument("-l", "--list", action="store_true", help="list available tests and exit") + parser.add_argument("-n", "--no-exec", action="store_true", help="no execute, just print the command line") + parser.add_argument("--path", action="append", default=[], help="additional $PATH directory") + parser.add_argument("-q", "--quiet", action="store_true", help="quiet, don't print anything unless there are failures") + parser.add_argument("-v", "--verbose", action="store_true", help="print configuration info and test results.") parser.add_argument('tests', nargs='*') args = parser.parse_args(argv[1:]) @@ -58,7 +48,7 @@ def main(argv=None): os.chdir(args.chdir) if args.path: - extra_path = [os.path.abspath(p) for p in opts.path] + extra_path = [os.path.abspath(p) for p in args.path] extra_path = os.pathsep.join(extra_path) os.environ['PATH'] = extra_path + os.pathsep + os.environ['PATH'] @@ -72,6 +62,9 @@ def main(argv=None): for arg in args.tests: if os.path.isdir(arg): tests.extend(find_all_gyptest_files(os.path.normpath(arg))) + elif '*' in arg: + glob_match = [t for t in glob(arg) if is_test_name(os.path.basename(t))] + tests.extend(glob_match) else: if not is_test_name(os.path.basename(arg)): print(arg, 'is not a valid gyp test name.', file=sys.stderr) @@ -83,8 +76,6 @@ def main(argv=None): print(test) sys.exit(0) - os.environ['PYTHONPATH'] = os.path.abspath('test/lib') - if args.verbose: print_configuration_info() @@ -95,20 +86,18 @@ def main(argv=None): format_list = args.format.split(',') else: format_list = { - 'aix5': ['make'], + 'aix5': ['make'], 'freebsd7': ['make'], 'freebsd8': ['make'], 'openbsd5': ['make'], - 'cygwin': ['msvs'], - 'win32': ['msvs', 'ninja'], - 'linux': ['make', 'ninja'], - 'linux2': ['make', 'ninja'], - 'linux3': ['make', 'ninja'], - - # TODO: Re-enable xcode-ninja. - # https://bugs.chromium.org/p/gyp/issues/detail?id=530 + 'cygwin': ['msvs'], + 'win32': ['msvs', 'ninja'], + 'linux': ['make', 'ninja'], + 'linux2': ['make', 'ninja'], + 'linux3': ['make', 'ninja'], + # TODO: Re-enable xcode-ninja. https://bugs.chromium.org/p/gyp/issues/detail?id=530 # 'darwin': ['make', 'ninja', 'xcode', 'xcode-ninja'], - 'darwin': ['make', 'ninja', 'xcode'], + 'darwin': ['make', 'ninja', 'xcode'], }[sys.platform] gyp_options = [] @@ -130,19 +119,30 @@ def main(argv=None): def print_configuration_info(): print('Test configuration:') if sys.platform == 'darwin': - sys.path.append(os.path.abspath('test/lib')) - import TestMac print(' Mac %s %s' % (platform.mac_ver()[0], platform.mac_ver()[2])) - print(' Xcode %s' % TestMac.Xcode.Version()) + try: + from XCodeDetect import XCodeDetect + print(' Xcode %s' % XCodeDetect.Version()) + except: + pass elif sys.platform == 'win32': - sys.path.append(os.path.abspath('pylib')) - import gyp.MSVSVersion print(' Win %s %s\n' % platform.win32_ver()[0:2]) - print(' MSVS %s' % - gyp.MSVSVersion.SelectVisualStudioVersion().Description()) + try: + from MSVS import MSVSVersion + version = MSVSVersion.SelectVisualStudioVersion() + print(' MSVS %s' % version.description) + except Exception: + pass elif sys.platform in ('linux', 'linux2'): - print(' Linux %s' % ' '.join(platform.linux_distribution())) - print(' Python %s' % platform.python_version()) + # noinspection PyBroadException + try: + with open('/etc/lsb-release', mode='r', encoding='utf-8') as f: + dist = f.read().strip() + print(' Linux %s' % dist) + except: + pass + + print(' Python %s %s' % (sys.executable, platform.python_version())) print(' PYTHONPATH=%s' % os.environ['PYTHONPATH']) print() @@ -155,74 +155,64 @@ def __init__(self, formats, tests, gyp_options, verbose): self.gyp_options = gyp_options self.failures = [] self.num_tests = len(formats) * len(tests) - num_digits = len(str(self.num_tests)) - self.fmt_str = '[%%%dd/%%%dd] (%%s) %%s' % (num_digits, num_digits) self.isatty = sys.stdout.isatty() and not self.verbose self.env = os.environ.copy() self.hpos = 0 + self.took = 0 def run(self): - run_start = time.time() + print('TAP version 13') + print('0..%d' % self.num_tests) - i = 1 - for fmt in self.formats: - for test in self.tests: - self.run_test(test, fmt, i) - i += 1 + run_start = time.time() - if self.isatty: - self.erase_current_line() + tests = [(t, f) for t in self.tests for f in self.formats] + for i, (test, fmt) in enumerate(tests, 1): + if self.verbose: + print('# %s %s' % (test, fmt)) + res, took, stdout, stderr = self.run_test(test, fmt) + print(res % (i, test + ' ' + fmt)) + print(' ---') + print(' duration_ms: %.3f' % took) + if len(stdout): + print(' stdout: |-') + for l in stdout.splitlines(): + print(' ', l) + stderr_lines = [l for l in stderr.splitlines() if 'pydev debugger' not in l] + if len(stderr_lines) and stderr_lines[-1] != 'PASSED': + print(' stderr: |-') + for l in stderr_lines: + print(' ', l) + print(' ...') self.took = time.time() - run_start - def run_test(self, test, fmt, i): - if self.isatty: - self.erase_current_line() + def run_test(self, test, fmt): + cmd = [sys.executable, test] + self.gyp_options + self.env['TESTGYP_FORMAT'] = fmt - msg = self.fmt_str % (i, self.num_tests, fmt, test) - self.print_(msg) + stderr_fd = subprocess.PIPE + if self.verbose: + self.env['TESTCMD_VERBOSE'] = '1' + # this will stream STDOUT to the parent's but will not pipe it to us... + # something something `while not proc.poll()`... + stderr_fd = None start = time.time() - cmd = [sys.executable, test] + self.gyp_options - self.env['TESTGYP_FORMAT'] = fmt - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, env=self.env) - proc.wait() + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=stderr_fd, env=self.env, universal_newlines=True) + stdout, stderr = proc.communicate() took = time.time() - start + stdout = stdout.strip() + stderr = (stderr or '').strip() - stdout = proc.stdout.read().decode('utf8') if proc.returncode == 2: - res = 'skipped' + res = 'not ok %d # skip %s' elif proc.returncode: - res = 'failed' + res = 'not ok %d %s' self.failures.append('(%s) %s' % (test, fmt)) else: - res = 'passed' - res_msg = ' %s %.3fs' % (res, took) - self.print_(res_msg) - - if (stdout and - not stdout.endswith('PASSED\n') and - not (stdout.endswith('NO RESULT\n'))): - print() - for l in stdout.splitlines(): - print(' %s' % l) - elif not self.isatty: - print() - - def print_(self, msg): - print(msg, end='') - index = msg.rfind('\n') - if index == -1: - self.hpos += len(msg) - else: - self.hpos = len(msg) - index - sys.stdout.flush() - - def erase_current_line(self): - print('\b' * self.hpos + ' ' * self.hpos + '\b' * self.hpos, end='') - sys.stdout.flush() - self.hpos = 0 + res = 'ok %d %s' + return res, took, stdout, stderr def print_results(self): num_failures = len(self.failures) @@ -234,10 +224,10 @@ def print_results(self): print("Failed the following %d tests:" % num_failures) print("\t" + "\n\t".join(sorted(self.failures))) print() - print('Ran %d tests in %.3fs, %d failed.' % (self.num_tests, self.took, - num_failures)) + print('Ran %d tests in %.3fs, %d failed.' % (self.num_tests, self.took, num_failures)) print() if __name__ == "__main__": - sys.exit(main()) + ret = main(sys.argv) + sys.exit(ret) diff --git a/tools/gyp/pylib/gyp/MSVSProject.py b/tools/gyp/pylib/gyp/MSVSProject.py deleted file mode 100644 index db1ceede344c60..00000000000000 --- a/tools/gyp/pylib/gyp/MSVSProject.py +++ /dev/null @@ -1,208 +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. - -"""Visual Studio project reader/writer.""" - -import gyp.common -import gyp.easy_xml as easy_xml - -#------------------------------------------------------------------------------ - - -class Tool(object): - """Visual Studio tool.""" - - def __init__(self, name, attrs=None): - """Initializes the tool. - - Args: - name: Tool name. - attrs: Dict of tool attributes; may be None. - """ - self._attrs = attrs or {} - self._attrs['Name'] = name - - def _GetSpecification(self): - """Creates an element for the tool. - - Returns: - A new xml.dom.Element for the tool. - """ - return ['Tool', self._attrs] - -class Filter(object): - """Visual Studio filter - that is, a virtual folder.""" - - def __init__(self, name, contents=None): - """Initializes the folder. - - Args: - name: Filter (folder) name. - contents: List of filenames and/or Filter objects contained. - """ - self.name = name - self.contents = list(contents or []) - - -#------------------------------------------------------------------------------ - - -class Writer(object): - """Visual Studio XML project writer.""" - - def __init__(self, project_path, version, name, guid=None, platforms=None): - """Initializes the project. - - Args: - project_path: Path to the project file. - version: Format version to emit. - name: Name of the project. - guid: GUID to use for project, if not None. - platforms: Array of string, the supported platforms. If null, ['Win32'] - """ - self.project_path = project_path - self.version = version - self.name = name - self.guid = guid - - # Default to Win32 for platforms. - if not platforms: - platforms = ['Win32'] - - # Initialize the specifications of the various sections. - self.platform_section = ['Platforms'] - for platform in platforms: - self.platform_section.append(['Platform', {'Name': platform}]) - self.tool_files_section = ['ToolFiles'] - self.configurations_section = ['Configurations'] - self.files_section = ['Files'] - - # Keep a dict keyed on filename to speed up access. - self.files_dict = dict() - - def AddToolFile(self, path): - """Adds a tool file to the project. - - Args: - path: Relative path from project to tool file. - """ - self.tool_files_section.append(['ToolFile', {'RelativePath': path}]) - - def _GetSpecForConfiguration(self, config_type, config_name, attrs, tools): - """Returns the specification for a configuration. - - Args: - config_type: Type of configuration node. - config_name: Configuration name. - attrs: Dict of configuration attributes; may be None. - tools: List of tools (strings or Tool objects); may be None. - Returns: - """ - # Handle defaults - if not attrs: - attrs = {} - if not tools: - tools = [] - - # Add configuration node and its attributes - node_attrs = attrs.copy() - node_attrs['Name'] = config_name - specification = [config_type, node_attrs] - - # Add tool nodes and their attributes - if tools: - for t in tools: - if isinstance(t, Tool): - specification.append(t._GetSpecification()) - else: - specification.append(Tool(t)._GetSpecification()) - return specification - - - def AddConfig(self, name, attrs=None, tools=None): - """Adds a configuration to the project. - - Args: - name: Configuration name. - attrs: Dict of configuration attributes; may be None. - tools: List of tools (strings or Tool objects); may be None. - """ - spec = self._GetSpecForConfiguration('Configuration', name, attrs, tools) - self.configurations_section.append(spec) - - def _AddFilesToNode(self, parent, files): - """Adds files and/or filters to the parent node. - - Args: - parent: Destination node - files: A list of Filter objects and/or relative paths to files. - - Will call itself recursively, if the files list contains Filter objects. - """ - for f in files: - if isinstance(f, Filter): - node = ['Filter', {'Name': f.name}] - self._AddFilesToNode(node, f.contents) - else: - node = ['File', {'RelativePath': f}] - self.files_dict[f] = node - parent.append(node) - - def AddFiles(self, files): - """Adds files to the project. - - Args: - files: A list of Filter objects and/or relative paths to files. - - This makes a copy of the file/filter tree at the time of this call. If you - later add files to a Filter object which was passed into a previous call - to AddFiles(), it will not be reflected in this project. - """ - self._AddFilesToNode(self.files_section, files) - # TODO(rspangler) This also doesn't handle adding files to an existing - # filter. That is, it doesn't merge the trees. - - def AddFileConfig(self, path, config, attrs=None, tools=None): - """Adds a configuration to a file. - - Args: - path: Relative path to the file. - config: Name of configuration to add. - attrs: Dict of configuration attributes; may be None. - tools: List of tools (strings or Tool objects); may be None. - - Raises: - ValueError: Relative path does not match any file added via AddFiles(). - """ - # Find the file node with the right relative path - parent = self.files_dict.get(path) - if not parent: - raise ValueError('AddFileConfig: file "%s" not in project.' % path) - - # Add the config to the file node - spec = self._GetSpecForConfiguration('FileConfiguration', config, attrs, - tools) - parent.append(spec) - - def WriteIfChanged(self): - """Writes the project file.""" - # First create XML content definition - content = [ - 'VisualStudioProject', - {'ProjectType': 'Visual C++', - 'Version': self.version.ProjectVersion(), - 'Name': self.name, - 'ProjectGUID': self.guid, - 'RootNamespace': self.name, - 'Keyword': 'Win32Proj' - }, - self.platform_section, - self.tool_files_section, - self.configurations_section, - ['References'], # empty section - self.files_section, - ['Globals'] # empty section - ] - easy_xml.WriteXmlIfChanged(content, self.project_path, - encoding="Windows-1252") diff --git a/tools/gyp/pylib/gyp/MSVSUserFile.py b/tools/gyp/pylib/gyp/MSVSUserFile.py deleted file mode 100644 index 6c07e9a893bac0..00000000000000 --- a/tools/gyp/pylib/gyp/MSVSUserFile.py +++ /dev/null @@ -1,147 +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. - -"""Visual Studio user preferences file writer.""" - -import os -import re -import socket # for gethostname - -import gyp.common -import gyp.easy_xml as easy_xml - - -#------------------------------------------------------------------------------ - -def _FindCommandInPath(command): - """If there are no slashes in the command given, this function - searches the PATH env to find the given command, and converts it - to an absolute path. We have to do this because MSVS is looking - for an actual file to launch a debugger on, not just a command - line. Note that this happens at GYP time, so anything needing to - be built needs to have a full path.""" - if '/' in command or '\\' in command: - # If the command already has path elements (either relative or - # absolute), then assume it is constructed properly. - return command - else: - # Search through the path list and find an existing file that - # we can access. - paths = os.environ.get('PATH','').split(os.pathsep) - for path in paths: - item = os.path.join(path, command) - if os.path.isfile(item) and os.access(item, os.X_OK): - return item - return command - -def _QuoteWin32CommandLineArgs(args): - new_args = [] - for arg in args: - # Replace all double-quotes with double-double-quotes to escape - # them for cmd shell, and then quote the whole thing if there - # are any. - if arg.find('"') != -1: - arg = '""'.join(arg.split('"')) - arg = '"%s"' % arg - - # Otherwise, if there are any spaces, quote the whole arg. - elif re.search(r'[ \t\n]', arg): - arg = '"%s"' % arg - new_args.append(arg) - return new_args - -class Writer(object): - """Visual Studio XML user user file writer.""" - - def __init__(self, user_file_path, version, name): - """Initializes the user file. - - Args: - user_file_path: Path to the user file. - version: Version info. - name: Name of the user file. - """ - self.user_file_path = user_file_path - self.version = version - self.name = name - self.configurations = {} - - def AddConfig(self, name): - """Adds a configuration to the project. - - Args: - name: Configuration name. - """ - self.configurations[name] = ['Configuration', {'Name': name}] - - def AddDebugSettings(self, config_name, command, environment = {}, - working_directory=""): - """Adds a DebugSettings node to the user file for a particular config. - - Args: - command: command line to run. First element in the list is the - executable. All elements of the command will be quoted if - necessary. - working_directory: other files which may trigger the rule. (optional) - """ - command = _QuoteWin32CommandLineArgs(command) - - abs_command = _FindCommandInPath(command[0]) - - if environment and isinstance(environment, dict): - env_list = ['%s="%s"' % (key, val) - for (key,val) in environment.iteritems()] - environment = ' '.join(env_list) - else: - environment = '' - - n_cmd = ['DebugSettings', - {'Command': abs_command, - 'WorkingDirectory': working_directory, - 'CommandArguments': " ".join(command[1:]), - 'RemoteMachine': socket.gethostname(), - 'Environment': environment, - 'EnvironmentMerge': 'true', - # Currently these are all "dummy" values that we're just setting - # in the default manner that MSVS does it. We could use some of - # these to add additional capabilities, I suppose, but they might - # not have parity with other platforms then. - 'Attach': 'false', - 'DebuggerType': '3', # 'auto' debugger - 'Remote': '1', - 'RemoteCommand': '', - 'HttpUrl': '', - 'PDBPath': '', - 'SQLDebugging': '', - 'DebuggerFlavor': '0', - 'MPIRunCommand': '', - 'MPIRunArguments': '', - 'MPIRunWorkingDirectory': '', - 'ApplicationCommand': '', - 'ApplicationArguments': '', - 'ShimCommand': '', - 'MPIAcceptMode': '', - 'MPIAcceptFilter': '' - }] - - # Find the config, and add it if it doesn't exist. - if config_name not in self.configurations: - self.AddConfig(config_name) - - # Add the DebugSettings onto the appropriate config. - self.configurations[config_name].append(n_cmd) - - def WriteIfChanged(self): - """Writes the user file.""" - configs = ['Configurations'] - for config, spec in sorted(self.configurations.iteritems()): - configs.append(spec) - - content = ['VisualStudioUserFile', - {'Version': self.version.ProjectVersion(), - 'Name': self.name - }, - configs] - easy_xml.WriteXmlIfChanged(content, self.user_file_path, - encoding="Windows-1252") diff --git a/tools/gyp/pylib/gyp/MSVSUtil.py b/tools/gyp/pylib/gyp/MSVSUtil.py deleted file mode 100644 index 96dea6c2c9d27f..00000000000000 --- a/tools/gyp/pylib/gyp/MSVSUtil.py +++ /dev/null @@ -1,271 +0,0 @@ -# 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. - -"""Utility functions shared amongst the Windows generators.""" - -import copy -import os - - -# A dictionary mapping supported target types to extensions. -TARGET_TYPE_EXT = { - 'executable': 'exe', - 'loadable_module': 'dll', - 'shared_library': 'dll', - 'static_library': 'lib', - 'windows_driver': 'sys', -} - - -def _GetLargePdbShimCcPath(): - """Returns the path of the large_pdb_shim.cc file.""" - this_dir = os.path.abspath(os.path.dirname(__file__)) - src_dir = os.path.abspath(os.path.join(this_dir, '..', '..')) - win_data_dir = os.path.join(src_dir, 'data', 'win') - large_pdb_shim_cc = os.path.join(win_data_dir, 'large-pdb-shim.cc') - return large_pdb_shim_cc - - -def _DeepCopySomeKeys(in_dict, keys): - """Performs a partial deep-copy on |in_dict|, only copying the keys in |keys|. - - Arguments: - in_dict: The dictionary to copy. - keys: The keys to be copied. If a key is in this list and doesn't exist in - |in_dict| this is not an error. - Returns: - The partially deep-copied dictionary. - """ - d = {} - for key in keys: - if key not in in_dict: - continue - d[key] = copy.deepcopy(in_dict[key]) - return d - - -def _SuffixName(name, suffix): - """Add a suffix to the end of a target. - - Arguments: - name: name of the target (foo#target) - suffix: the suffix to be added - Returns: - Target name with suffix added (foo_suffix#target) - """ - parts = name.rsplit('#', 1) - parts[0] = '%s_%s' % (parts[0], suffix) - return '#'.join(parts) - - -def _ShardName(name, number): - """Add a shard number to the end of a target. - - Arguments: - name: name of the target (foo#target) - number: shard number - Returns: - Target name with shard added (foo_1#target) - """ - return _SuffixName(name, str(number)) - - -def ShardTargets(target_list, target_dicts): - """Shard some targets apart to work around the linkers limits. - - Arguments: - target_list: List of target pairs: 'base/base.gyp:base'. - target_dicts: Dict of target properties keyed on target pair. - Returns: - Tuple of the new sharded versions of the inputs. - """ - # Gather the targets to shard, and how many pieces. - targets_to_shard = {} - for t in target_dicts: - shards = int(target_dicts[t].get('msvs_shard', 0)) - if shards: - targets_to_shard[t] = shards - # Shard target_list. - new_target_list = [] - for t in target_list: - if t in targets_to_shard: - for i in range(targets_to_shard[t]): - new_target_list.append(_ShardName(t, i)) - else: - new_target_list.append(t) - # Shard target_dict. - new_target_dicts = {} - for t in target_dicts: - if t in targets_to_shard: - for i in range(targets_to_shard[t]): - name = _ShardName(t, i) - new_target_dicts[name] = copy.copy(target_dicts[t]) - new_target_dicts[name]['target_name'] = _ShardName( - new_target_dicts[name]['target_name'], i) - sources = new_target_dicts[name].get('sources', []) - new_sources = [] - for pos in range(i, len(sources), targets_to_shard[t]): - new_sources.append(sources[pos]) - new_target_dicts[name]['sources'] = new_sources - else: - new_target_dicts[t] = target_dicts[t] - # Shard dependencies. - for t in sorted(new_target_dicts): - 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) - - -def _GetPdbPath(target_dict, config_name, vars): - """Returns the path to the PDB file that will be generated by a given - configuration. - - The lookup proceeds as follows: - - Look for an explicit path in the VCLinkerTool configuration block. - - Look for an 'msvs_large_pdb_path' variable. - - Use '<(PRODUCT_DIR)/<(product_name).(exe|dll).pdb' if 'product_name' is - specified. - - Use '<(PRODUCT_DIR)/<(target_name).(exe|dll).pdb'. - - Arguments: - target_dict: The target dictionary to be searched. - config_name: The name of the configuration of interest. - vars: A dictionary of common GYP variables with generator-specific values. - Returns: - The path of the corresponding PDB file. - """ - config = target_dict['configurations'][config_name] - msvs = config.setdefault('msvs_settings', {}) - - linker = msvs.get('VCLinkerTool', {}) - - pdb_path = linker.get('ProgramDatabaseFile') - if pdb_path: - return pdb_path - - variables = target_dict.get('variables', {}) - pdb_path = variables.get('msvs_large_pdb_path', None) - if pdb_path: - return pdb_path - - - 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_path = vars['PRODUCT_DIR'] + '/' + pdb_base - - return pdb_path - - -def InsertLargePdbShims(target_list, target_dicts, vars): - """Insert a shim target that forces the linker to use 4KB pagesize PDBs. - - This is a workaround for targets with PDBs greater than 1GB in size, the - limit for the 1KB pagesize PDBs created by the linker by default. - - Arguments: - target_list: List of target pairs: 'base/base.gyp:base'. - target_dicts: Dict of target properties keyed on target pair. - vars: A dictionary of common GYP variables with generator-specific values. - Returns: - Tuple of the shimmed version of the inputs. - """ - # Determine which targets need shimming. - targets_to_shim = [] - for t in target_dicts: - target_dict = target_dicts[t] - - # We only want to shim targets that have msvs_large_pdb enabled. - if not int(target_dict.get('msvs_large_pdb', 0)): - continue - # This is intended for executable, shared_library and loadable_module - # targets where every configuration is set up to produce a PDB output. - # If any of these conditions is not true then the shim logic will fail - # below. - targets_to_shim.append(t) - - large_pdb_shim_cc = _GetLargePdbShimCcPath() - - for t in targets_to_shim: - target_dict = target_dicts[t] - target_name = target_dict.get('target_name') - - base_dict = _DeepCopySomeKeys(target_dict, - ['configurations', 'default_configuration', 'toolset']) - - # This is the dict for copying the source file (part of the GYP tree) - # to the intermediate directory of the project. This is necessary because - # we can't always build a relative path to the shim source file (on Windows - # GYP and the project may be on different drives), and Ninja hates absolute - # paths (it ends up generating the .obj and .obj.d alongside the source - # file, polluting GYPs tree). - copy_suffix = 'large_pdb_copy' - copy_target_name = target_name + '_' + copy_suffix - full_copy_target_name = _SuffixName(t, copy_suffix) - shim_cc_basename = os.path.basename(large_pdb_shim_cc) - shim_cc_dir = vars['SHARED_INTERMEDIATE_DIR'] + '/' + copy_target_name - shim_cc_path = shim_cc_dir + '/' + shim_cc_basename - copy_dict = copy.deepcopy(base_dict) - copy_dict['target_name'] = copy_target_name - copy_dict['type'] = 'none' - copy_dict['sources'] = [ large_pdb_shim_cc ] - copy_dict['copies'] = [{ - 'destination': shim_cc_dir, - 'files': [ large_pdb_shim_cc ] - }] - - # This is the dict for the PDB generating shim target. It depends on the - # copy target. - shim_suffix = 'large_pdb_shim' - shim_target_name = target_name + '_' + shim_suffix - full_shim_target_name = _SuffixName(t, shim_suffix) - shim_dict = copy.deepcopy(base_dict) - shim_dict['target_name'] = shim_target_name - shim_dict['type'] = 'static_library' - shim_dict['sources'] = [ shim_cc_path ] - shim_dict['dependencies'] = [ full_copy_target_name ] - - # Set up the shim to output its PDB to the same location as the final linker - # target. - for config_name, config in shim_dict.get('configurations').iteritems(): - pdb_path = _GetPdbPath(target_dict, config_name, vars) - - # A few keys that we don't want to propagate. - for key in ['msvs_precompiled_header', 'msvs_precompiled_source', 'test']: - config.pop(key, None) - - msvs = config.setdefault('msvs_settings', {}) - - # Update the compiler directives in the shim target. - compiler = msvs.setdefault('VCCLCompilerTool', {}) - compiler['DebugInformationFormat'] = '3' - compiler['ProgramDataBaseFileName'] = pdb_path - - # Set the explicit PDB path in the appropriate configuration of the - # original target. - config = target_dict['configurations'][config_name] - msvs = config.setdefault('msvs_settings', {}) - linker = msvs.setdefault('VCLinkerTool', {}) - linker['GenerateDebugInformation'] = 'true' - linker['ProgramDatabaseFile'] = pdb_path - - # Add the new targets. They must go to the beginning of the list so that - # the dependency generation works as expected in ninja. - target_list.insert(0, full_copy_target_name) - target_list.insert(0, full_shim_target_name) - target_dicts[full_copy_target_name] = copy_dict - target_dicts[full_shim_target_name] = shim_dict - - # Update the original target to depend on the shim target. - target_dict.setdefault('dependencies', []).append(full_shim_target_name) - - return (target_list, target_dicts) diff --git a/tools/gyp/pylib/gyp/MSVSVersion.py b/tools/gyp/pylib/gyp/MSVSVersion.py deleted file mode 100644 index 44b958d5b3d22e..00000000000000 --- a/tools/gyp/pylib/gyp/MSVSVersion.py +++ /dev/null @@ -1,491 +0,0 @@ -# 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. - -"""Handle version information related to Visual Stuio.""" - -import errno -import os -import re -import subprocess -import sys -import gyp -import glob - - -def JoinPath(*args): - return os.path.normpath(os.path.join(*args)) - - -class VisualStudioVersion(object): - """Information regarding a version of Visual Studio.""" - - def __init__(self, short_name, description, - solution_version, project_version, flat_sln, uses_vcxproj, - path, sdk_based, default_toolset=None, compatible_sdks=None): - self.short_name = short_name - self.description = description - self.solution_version = solution_version - self.project_version = project_version - self.flat_sln = flat_sln - self.uses_vcxproj = uses_vcxproj - self.path = path - self.sdk_based = sdk_based - self.default_toolset = default_toolset - compatible_sdks = compatible_sdks or [] - compatible_sdks.sort(key=lambda v: float(v.replace('v', '')), reverse=True) - self.compatible_sdks = compatible_sdks - - def ShortName(self): - return self.short_name - - def Description(self): - """Get the full description of the version.""" - return self.description - - def SolutionVersion(self): - """Get the version number of the sln files.""" - return self.solution_version - - def ProjectVersion(self): - """Get the version number of the vcproj or vcxproj files.""" - return self.project_version - - def FlatSolution(self): - return self.flat_sln - - def UsesVcxproj(self): - """Returns true if this version uses a vcxproj file.""" - return self.uses_vcxproj - - def ProjectExtension(self): - """Returns the file extension for the project.""" - return self.uses_vcxproj and '.vcxproj' or '.vcproj' - - def Path(self): - """Returns the path to Visual Studio installation.""" - return self.path - - def ToolPath(self, tool): - """Returns the path to a given compiler tool. """ - return os.path.normpath(os.path.join(self.path, "VC/bin", tool)) - - def DefaultToolset(self): - """Returns the msbuild toolset version that will be used in the absence - of a user override.""" - return self.default_toolset - - - def _SetupScriptInternal(self, target_arch): - """Returns a command (with arguments) to be used to set up the - environment.""" - assert target_arch in ('x86', 'x64'), "target_arch not supported" - # If WindowsSDKDir is set and SetEnv.Cmd exists then we are using the - # depot_tools build tools and should run SetEnv.Cmd to set up the - # environment. The check for WindowsSDKDir alone is not sufficient because - # this is set by running vcvarsall.bat. - sdk_dir = os.environ.get('WindowsSDKDir', '') - setup_path = JoinPath(sdk_dir, 'Bin', 'SetEnv.Cmd') - if self.sdk_based and sdk_dir and os.path.exists(setup_path): - return [setup_path, '/' + target_arch] - - is_host_arch_x64 = ( - os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or - os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64' - ) - - # For VS2017 (and newer) it's fairly easy - if self.short_name >= '2017': - script_path = JoinPath(self.path, - 'VC', 'Auxiliary', 'Build', 'vcvarsall.bat') - - # Always use a native executable, cross-compiling if necessary. - host_arch = 'amd64' if is_host_arch_x64 else 'x86' - msvc_target_arch = 'amd64' if target_arch == 'x64' else 'x86' - arg = host_arch - if host_arch != msvc_target_arch: - arg += '_' + msvc_target_arch - - return [script_path, arg] - - # We try to find the best version of the env setup batch. - vcvarsall = JoinPath(self.path, 'VC', 'vcvarsall.bat') - if target_arch == 'x86': - if self.short_name >= '2013' and self.short_name[-1] != 'e' and \ - is_host_arch_x64: - # VS2013 and later, non-Express have a x64-x86 cross that we want - # to prefer. - return [vcvarsall, 'amd64_x86'] - else: - # Otherwise, the standard x86 compiler. We don't use VC/vcvarsall.bat - # for x86 because vcvarsall calls vcvars32, which it can only find if - # VS??COMNTOOLS is set, which isn't guaranteed. - return [JoinPath(self.path, 'Common7', 'Tools', 'vsvars32.bat')] - elif target_arch == 'x64': - arg = 'x86_amd64' - # 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 is_host_arch_x64: - arg = 'amd64' - return [vcvarsall, arg] - - def SetupScript(self, target_arch): - script_data = self._SetupScriptInternal(target_arch) - script_path = script_data[0] - if not os.path.exists(script_path): - raise Exception('%s is missing - make sure VC++ tools are installed.' % - script_path) - return script_data - - -def _RegistryQueryBase(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) - # Obtain 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 _RegistryQuery(key, value=None): - 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 - 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 = _RegistryQueryBase('Sysnative', key, value) - except OSError, e: - if e.errno == errno.ENOENT: - text = _RegistryQueryBase('System32', key, value) - else: - raise - 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 _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. - value: The particular registry value to read. - 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 - # Extract value. - match = re.search(r'REG_\w+\s+([^\r]+)\r\n', text) - if not match: - return None - return match.group(1) - - -def _CreateVersion(name, path, sdk_based=False): - """Sets up MSVS project generation. - - Setup is based off the GYP_MSVS_VERSION environment variable or whatever is - autodetected if GYP_MSVS_VERSION is not explicitly specified. If a version is - passed in that doesn't match a value in versions python will throw a error. - """ - if path: - path = os.path.normpath(path) - versions = { - '2017': VisualStudioVersion('2017', - 'Visual Studio 2017', - solution_version='12.00', - project_version='15.0', - flat_sln=False, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based, - default_toolset='v141', - compatible_sdks=['v8.1', 'v10.0']), - '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', - project_version='12.0', - flat_sln=False, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based, - default_toolset='v120'), - '2013e': VisualStudioVersion('2013e', - 'Visual Studio 2013', - solution_version='13.00', - project_version='12.0', - flat_sln=True, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based, - default_toolset='v120'), - '2012': VisualStudioVersion('2012', - 'Visual Studio 2012', - solution_version='12.00', - project_version='4.0', - flat_sln=False, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based, - default_toolset='v110'), - '2012e': VisualStudioVersion('2012e', - 'Visual Studio 2012', - solution_version='12.00', - project_version='4.0', - flat_sln=True, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based, - default_toolset='v110'), - '2010': VisualStudioVersion('2010', - 'Visual Studio 2010', - solution_version='11.00', - project_version='4.0', - flat_sln=False, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based), - '2010e': VisualStudioVersion('2010e', - 'Visual C++ Express 2010', - solution_version='11.00', - project_version='4.0', - flat_sln=True, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based), - '2008': VisualStudioVersion('2008', - 'Visual Studio 2008', - solution_version='10.00', - project_version='9.00', - flat_sln=False, - uses_vcxproj=False, - path=path, - sdk_based=sdk_based), - '2008e': VisualStudioVersion('2008e', - 'Visual Studio 2008', - solution_version='10.00', - project_version='9.00', - flat_sln=True, - uses_vcxproj=False, - path=path, - sdk_based=sdk_based), - '2005': VisualStudioVersion('2005', - 'Visual Studio 2005', - solution_version='9.00', - project_version='8.00', - flat_sln=False, - uses_vcxproj=False, - path=path, - sdk_based=sdk_based), - '2005e': VisualStudioVersion('2005e', - 'Visual Studio 2005', - solution_version='9.00', - project_version='8.00', - flat_sln=True, - uses_vcxproj=False, - path=path, - sdk_based=sdk_based), - } - return versions[str(name)] - - -def _ConvertToCygpath(path): - """Convert to cygwin path if we are using cygwin.""" - if sys.platform == 'cygwin': - p = subprocess.Popen(['cygpath', path], stdout=subprocess.PIPE) - path = p.communicate()[0].strip() - return path - - -def _DetectVisualStudioVersions(versions_to_check, force_express): - """Collect the list of installed visual studio versions. - - Returns: - A list of visual studio versions installed in descending order of - usage preference. - Base this on the registry and a quick check if devenv.exe exists. - Possibilities are: - 2005(e) - Visual Studio 2005 (8) - 2008(e) - Visual Studio 2008 (9) - 2010(e) - Visual Studio 2010 (10) - 2012(e) - Visual Studio 2012 (11) - 2013(e) - Visual Studio 2013 (12) - 2015 - Visual Studio 2015 (14) - 2017 - Visual Studio 2017 (15) - Where (e) is e for express editions of MSVS and blank otherwise. - """ - version_to_year = { - '8.0': '2005', - '9.0': '2008', - '10.0': '2010', - '11.0': '2012', - '12.0': '2013', - '14.0': '2015', - '15.0': '2017' - } - versions = [] - for version in versions_to_check: - # Old method of searching for which VS version is installed - # We don't use the 2010-encouraged-way because we also want to get the - # path to the binaries, which it doesn't offer. - keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version, - r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version, - r'HKLM\Software\Microsoft\VCExpress\%s' % version, - r'HKLM\Software\Wow6432Node\Microsoft\VCExpress\%s' % version] - for index in range(len(keys)): - path = _RegistryGetValue(keys[index], 'InstallDir') - if not path: - continue - path = _ConvertToCygpath(path) - # Check for full. - full_path = os.path.join(path, 'devenv.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 glob.glob(express_path): - # Add this one. - versions.append(_CreateVersion(version_to_year[version] + 'e', - os.path.join(path, '..', '..'))) - - # The old method above does not work when only SDK is installed. - keys = [r'HKLM\Software\Microsoft\VisualStudio\SxS\VC7', - r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7', - r'HKLM\Software\Microsoft\VisualStudio\SxS\VS7', - r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VS7'] - for index in range(len(keys)): - path = _RegistryGetValue(keys[index], version) - if not path: - continue - path = _ConvertToCygpath(path) - if version == '15.0': - if os.path.exists(path): - versions.append(_CreateVersion('2017', path)) - elif 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', allow_fallback=True): - """Select which version of Visual Studio projects to generate. - - Arguments: - version: Hook to allow caller to force a particular version (vs auto). - Returns: - An object representing a visual studio project format version. - """ - # In auto mode, check environment variable for override. - if version == 'auto': - version = os.environ.get('GYP_MSVS_VERSION', 'auto') - version_map = { - 'auto': ('15.0', '14.0', '12.0', '10.0', '9.0', '8.0', '11.0'), - '2005': ('8.0',), - '2005e': ('8.0',), - '2008': ('9.0',), - '2008e': ('9.0',), - '2010': ('10.0',), - '2010e': ('10.0',), - '2012': ('11.0',), - '2012e': ('11.0',), - '2013': ('12.0',), - '2013e': ('12.0',), - '2015': ('14.0',), - '2017': ('15.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: - raise ValueError('GYP_MSVS_OVERRIDE_PATH requires GYP_MSVS_VERSION to be ' - '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) - else: - return _CreateVersion(version, None) - return versions[0] diff --git a/tools/gyp/pylib/gyp/generator/compile_commands_json.py b/tools/gyp/pylib/gyp/generator/compile_commands_json.py deleted file mode 100644 index 575db63c4e1943..00000000000000 --- a/tools/gyp/pylib/gyp/generator/compile_commands_json.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright (c) 2016 Ben Noordhuis . All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import gyp.common -import gyp.xcode_emulation -import json -import os - -generator_additional_non_configuration_keys = [] -generator_additional_path_sections = [] -generator_extra_sources_for_rules = [] -generator_filelist_paths = None -generator_supports_multiple_toolsets = True -generator_wants_sorted_dependencies = False - -# Lifted from make.py. The actual values don't matter much. -generator_default_variables = { - 'CONFIGURATION_NAME': '$(BUILDTYPE)', - 'EXECUTABLE_PREFIX': '', - 'EXECUTABLE_SUFFIX': '', - 'INTERMEDIATE_DIR': '$(obj).$(TOOLSET)/$(TARGET)/geni', - 'PRODUCT_DIR': '$(builddir)', - 'RULE_INPUT_DIRNAME': '%(INPUT_DIRNAME)s', - 'RULE_INPUT_EXT': '$(suffix $<)', - 'RULE_INPUT_NAME': '$(notdir $<)', - 'RULE_INPUT_PATH': '$(abspath $<)', - 'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', - 'SHARED_INTERMEDIATE_DIR': '$(obj)/gen', - 'SHARED_LIB_PREFIX': 'lib', - 'STATIC_LIB_PREFIX': 'lib', - 'STATIC_LIB_SUFFIX': '.a', -} - - -def IsMac(params): - return 'mac' == gyp.common.GetFlavor(params) - - -def CalculateVariables(default_variables, params): - default_variables.setdefault('OS', gyp.common.GetFlavor(params)) - - -def AddCommandsForTarget(cwd, target, params, per_config_commands): - output_dir = params['generator_flags']['output_dir'] - for configuration_name, configuration in target['configurations'].iteritems(): - builddir_name = os.path.join(output_dir, configuration_name) - - if IsMac(params): - xcode_settings = gyp.xcode_emulation.XcodeSettings(target) - cflags = xcode_settings.GetCflags(configuration_name) - cflags_c = xcode_settings.GetCflagsC(configuration_name) - cflags_cc = xcode_settings.GetCflagsCC(configuration_name) - else: - cflags = configuration.get('cflags', []) - cflags_c = configuration.get('cflags_c', []) - cflags_cc = configuration.get('cflags_cc', []) - - cflags_c = cflags + cflags_c - cflags_cc = cflags + cflags_cc - - defines = configuration.get('defines', []) - defines = ['-D' + s for s in defines] - - # TODO(bnoordhuis) Handle generated source files. - sources = target.get('sources', []) - sources = [s for s in sources if s.endswith('.c') or s.endswith('.cc')] - - def resolve(filename): - return os.path.abspath(os.path.join(cwd, filename)) - - # TODO(bnoordhuis) Handle generated header files. - include_dirs = configuration.get('include_dirs', []) - include_dirs = [s for s in include_dirs if not s.startswith('$(obj)')] - includes = ['-I' + resolve(s) for s in include_dirs] - - defines = gyp.common.EncodePOSIXShellList(defines) - includes = gyp.common.EncodePOSIXShellList(includes) - cflags_c = gyp.common.EncodePOSIXShellList(cflags_c) - cflags_cc = gyp.common.EncodePOSIXShellList(cflags_cc) - - commands = per_config_commands.setdefault(configuration_name, []) - for source in sources: - file = resolve(source) - isc = source.endswith('.c') - cc = 'cc' if isc else 'c++' - cflags = cflags_c if isc else cflags_cc - command = ' '.join((cc, defines, includes, cflags, - '-c', gyp.common.EncodePOSIXShellArgument(file))) - commands.append(dict(command=command, directory=output_dir, file=file)) - - -def GenerateOutput(target_list, target_dicts, data, params): - per_config_commands = {} - for qualified_target, target in target_dicts.iteritems(): - build_file, target_name, toolset = ( - gyp.common.ParseQualifiedTarget(qualified_target)) - if IsMac(params): - settings = data[build_file] - gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(settings, target) - cwd = os.path.dirname(build_file) - AddCommandsForTarget(cwd, target, params, per_config_commands) - - output_dir = params['generator_flags']['output_dir'] - for configuration_name, commands in per_config_commands.iteritems(): - filename = os.path.join(output_dir, - configuration_name, - 'compile_commands.json') - gyp.common.EnsureDirExists(filename) - fp = open(filename, 'w') - json.dump(commands, fp=fp, indent=0, check_circular=False) - - -def PerformBuild(data, configurations, params): - pass diff --git a/tools/gyp/pylib/gyp/generator/ninja.py b/tools/gyp/pylib/gyp/generator/ninja.py deleted file mode 100644 index 6140df9513096c..00000000000000 --- a/tools/gyp/pylib/gyp/generator/ninja.py +++ /dev/null @@ -1,2488 +0,0 @@ -# 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 collections -import copy -import hashlib -import json -import multiprocessing -import os.path -import re -import signal -import subprocess -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 -from cStringIO import StringIO - -from gyp.common import GetEnvironFallback -import gyp.ninja_syntax as ninja_syntax - -generator_default_variables = { - 'EXECUTABLE_PREFIX': '', - 'EXECUTABLE_SUFFIX': '', - 'STATIC_LIB_PREFIX': 'lib', - 'STATIC_LIB_SUFFIX': '.a', - 'SHARED_LIB_PREFIX': 'lib', - - # Gyp expects the following variables to be expandable by the build - # system to the appropriate locations. Ninja prefers paths to be - # known at gyp time. To resolve this, introduce special - # variables starting with $! and $| (which begin with a $ so gyp knows it - # should be treated specially, but is otherwise an invalid - # ninja/shell variable) that are passed to gyp here but expanded - # before writing out into the target .ninja files; see - # ExpandSpecial. - # $! is used for variables that represent a path and that can only appear at - # the start of a string, while $| is used for variables that can appear - # anywhere in a string. - 'INTERMEDIATE_DIR': '$!INTERMEDIATE_DIR', - 'SHARED_INTERMEDIATE_DIR': '$!PRODUCT_DIR/gen', - 'PRODUCT_DIR': '$!PRODUCT_DIR', - 'CONFIGURATION_NAME': '$|CONFIGURATION_NAME', - - # Special variables that may be used by gyp 'rule' targets. - # We generate definitions for these variables on the fly when processing a - # rule. - 'RULE_INPUT_ROOT': '${root}', - 'RULE_INPUT_DIRNAME': '${dirname}', - 'RULE_INPUT_PATH': '${source}', - 'RULE_INPUT_EXT': '${ext}', - 'RULE_INPUT_NAME': '${name}', -} - -# Placates pylint. -generator_additional_non_configuration_keys = [] -generator_additional_path_sections = [] -generator_extra_sources_for_rules = [] -generator_filelist_paths = None - -generator_supports_multiple_toolsets = gyp.common.CrossCompileRequested() - -def StripPrefix(arg, prefix): - if arg.startswith(prefix): - return arg[len(prefix):] - return arg - - -def QuoteShellArgument(arg, flavor): - """Quote a string such that it will be interpreted as a single argument - by the shell.""" - # Rather than attempting to enumerate the bad shell characters, just - # whitelist common OK ones and quote anything else. - if re.match(r'^[a-zA-Z0-9_=.\\/-]+$', arg): - return arg # No quoting necessary. - if flavor == 'win': - return gyp.msvs_emulation.QuoteForRspFile(arg) - return "'" + arg.replace("'", "'" + '"\'"' + "'") + "'" - - -def Define(d, flavor): - """Takes a preprocessor define and returns a -D parameter that's ninja- and - shell-escaped.""" - if flavor == 'win': - # cl.exe replaces literal # characters with = in preprocesor definitions for - # some reason. Octal-encode to work around that. - d = d.replace('#', '\\%03o' % ord('#')) - return QuoteShellArgument(ninja_syntax.escape('-D' + d), flavor) - - -def AddArch(output, arch): - """Adds an arch string to an output path.""" - output, extension = os.path.splitext(output) - return '%s.%s%s' % (output, arch, extension) - - -class Target(object): - """Target represents the paths used within a single gyp target. - - Conceptually, building a single target A is a series of steps: - - 1) actions/rules/copies generates source/resources/etc. - 2) compiles generates .o files - 3) link generates a binary (library/executable) - 4) bundle merges the above in a mac bundle - - (Any of these steps can be optional.) - - From a build ordering perspective, a dependent target B could just - depend on the last output of this series of steps. - - But some dependent commands sometimes need to reach inside the box. - For example, when linking B it needs to get the path to the static - library generated by A. - - This object stores those paths. To keep things simple, member - variables only store concrete paths to single files, while methods - compute derived values like "the last output of the target". - """ - def __init__(self, type): - # Gyp type ("static_library", etc.) of this target. - self.type = type - # File representing whether any input dependencies necessary for - # dependent actions have completed. - self.preaction_stamp = None - # File representing whether any input dependencies necessary for - # dependent compiles have completed. - self.precompile_stamp = None - # File representing the completion of actions/rules/copies, if any. - self.actions_stamp = None - # Path to the output of the link step, if any. - self.binary = None - # Path to the file representing the completion of building the bundle, - # if any. - self.bundle = None - # On Windows, incremental linking requires linking against all the .objs - # that compose a .lib (rather than the .lib itself). That list is stored - # here. In this case, we also need to save the compile_deps for the target, - # so that the target that directly depends on the .objs can also depend - # on those. - self.component_objs = None - self.compile_deps = None - # Windows only. The import .lib is the output of a build step, but - # because dependents only link against the lib (not both the lib and the - # dll) we keep track of the import library here. - self.import_lib = None - # Track if this target contains any C++ files, to decide if gcc or g++ - # should be used for linking. - self.uses_cpp = False - - def Linkable(self): - """Return true if this is a target that can be linked against.""" - return self.type in ('static_library', 'shared_library') - - def UsesToc(self, flavor): - """Return true if the target should produce a restat rule based on a TOC - file.""" - # For bundles, the .TOC should be produced for the binary, not for - # FinalOutput(). But the naive approach would put the TOC file into the - # bundle, so don't do this for bundles for now. - if flavor == 'win' or self.bundle: - return False - return self.type in ('shared_library', 'loadable_module') - - def PreActionInput(self, flavor): - """Return the path, if any, that should be used as a dependency of - any dependent action step.""" - if self.UsesToc(flavor): - return self.FinalOutput() + '.TOC' - return self.FinalOutput() or self.preaction_stamp - - def PreCompileInput(self): - """Return the path, if any, that should be used as a dependency of - any dependent compile step.""" - return self.actions_stamp or self.precompile_stamp - - def FinalOutput(self): - """Return the last output of the target, which depends on all prior - steps.""" - return self.bundle or self.binary or self.actions_stamp - - -# A small discourse on paths as used within the Ninja build: -# All files we produce (both at gyp and at build time) appear in the -# build directory (e.g. out/Debug). -# -# Paths within a given .gyp file are always relative to the directory -# containing the .gyp file. Call these "gyp paths". This includes -# sources as well as the starting directory a given gyp rule/action -# expects to be run from. We call the path from the source root to -# the gyp file the "base directory" within the per-.gyp-file -# NinjaWriter code. -# -# All paths as written into the .ninja files are relative to the build -# directory. Call these paths "ninja paths". -# -# We translate between these two notions of paths with two helper -# functions: -# -# - GypPathToNinja translates a gyp path (i.e. relative to the .gyp file) -# into the equivalent ninja path. -# -# - GypPathToUniqueOutput translates a gyp path into a ninja path to write -# 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(object): - def __init__(self, hash_for_rules, target_outputs, base_dir, build_dir, - output_file, toplevel_build, output_file_name, flavor, - 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 - build_dir: path from source root to build output - toplevel_dir: path to the toplevel directory - """ - - self.hash_for_rules = hash_for_rules - self.target_outputs = target_outputs - self.base_dir = base_dir - self.build_dir = build_dir - self.ninja = ninja_syntax.Writer(output_file) - self.toplevel_build = toplevel_build - self.output_file_name = output_file_name - - self.flavor = flavor - self.abs_build_dir = None - if toplevel_dir is not None: - self.abs_build_dir = os.path.abspath(os.path.join(toplevel_dir, - build_dir)) - self.obj_ext = '.obj' if flavor == 'win' else '.o' - if flavor == 'win': - # See docstring of msvs_emulation.GenerateEnvironmentFiles(). - self.win_env = {} - for arch in ('x86', 'x64'): - self.win_env[arch] = 'environment.' + arch - - # Relative path from build output dir to base dir. - build_to_top = gyp.common.InvertRelativePath(build_dir, toplevel_dir) - self.build_to_base = os.path.join(build_to_top, base_dir) - # 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) - - def ExpandSpecial(self, path, product_dir=None): - """Expand specials like $!PRODUCT_DIR in |path|. - - If |product_dir| is None, assumes the cwd is already the product - dir. Otherwise, |product_dir| is the relative path to the product - dir. - """ - - PRODUCT_DIR = '$!PRODUCT_DIR' - if PRODUCT_DIR in path: - if product_dir: - path = path.replace(PRODUCT_DIR, product_dir) - else: - path = path.replace(PRODUCT_DIR + '/', '') - path = path.replace(PRODUCT_DIR + '\\', '') - path = path.replace(PRODUCT_DIR, '.') - - INTERMEDIATE_DIR = '$!INTERMEDIATE_DIR' - if INTERMEDIATE_DIR in path: - int_dir = self.GypPathToUniqueOutput('gen') - # GypPathToUniqueOutput generates a path relative to the product dir, - # so insert product_dir in front if it is provided. - path = path.replace(INTERMEDIATE_DIR, - os.path.join(product_dir or '', int_dir)) - - CONFIGURATION_NAME = '$|CONFIGURATION_NAME' - path = path.replace(CONFIGURATION_NAME, self.config_name) - - return path - - def ExpandRuleVariables(self, path, root, dirname, source, ext, name): - if self.flavor == 'win': - path = self.msvs_settings.ConvertVSMacros( - path, config=self.config_name) - path = path.replace(generator_default_variables['RULE_INPUT_ROOT'], root) - path = path.replace(generator_default_variables['RULE_INPUT_DIRNAME'], - dirname) - path = path.replace(generator_default_variables['RULE_INPUT_PATH'], source) - path = path.replace(generator_default_variables['RULE_INPUT_EXT'], ext) - path = path.replace(generator_default_variables['RULE_INPUT_NAME'], name) - return path - - def GypPathToNinja(self, path, env=None): - """Translate a gyp path to a ninja path, optionally expanding environment - variable references in |path| with |env|. - - See the above discourse on path conversions.""" - if env: - if self.flavor == 'mac': - path = gyp.xcode_emulation.ExpandEnvVars(path, env) - elif self.flavor == 'win': - path = gyp.msvs_emulation.ExpandMacros(path, env) - if path.startswith('$!'): - expanded = self.ExpandSpecial(path) - if self.flavor == 'win': - expanded = os.path.normpath(expanded) - return expanded - if '$|' in path: - path = self.ExpandSpecial(path) - assert '$' not in path, path - return os.path.normpath(os.path.join(self.build_to_base, path)) - - def GypPathToUniqueOutput(self, path, qualified=True): - """Translate a gyp path to a ninja path for writing output. - - If qualified is True, qualify the resulting filename with the name - of the target. This is necessary when e.g. compiling the same - path twice for two separate output targets. - - See the above discourse on path conversions.""" - - path = self.ExpandSpecial(path) - assert not path.startswith('$'), path - - # Translate the path following this scheme: - # Input: foo/bar.gyp, target targ, references baz/out.o - # Output: obj/foo/baz/targ.out.o (if qualified) - # obj/foo/baz/out.o (otherwise) - # (and obj.host instead of obj for cross-compiles) - # - # Why this scheme and not some other one? - # 1) for a given input, you can compute all derived outputs by matching - # its path, even if the input is brought via a gyp file with '..'. - # 2) simple files like libraries and stamps have a simple filename. - - obj = 'obj' - if self.toolset != 'target': - 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, 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. - - Uses a stamp file if necessary.""" - - assert targets == filter(None, targets), targets - if len(targets) == 0: - assert not order_only - return None - if len(targets) > 1 or order_only: - stamp = self.GypPathToUniqueOutput(name + '.stamp') - targets = self.ninja.build(stamp, 'stamp', targets, order_only=order_only) - self.ninja.newline() - return targets[0] - - def _SubninjaNameForArch(self, arch): - output_file_base = os.path.splitext(self.output_file_name)[0] - return '%s.%s.ninja' % (output_file_base, arch) - - def WriteSpec(self, spec, config_name, generator_flags): - """The main entry point for NinjaWriter: write the build rules for a spec. - - Returns a Target object, which represents the output paths for this spec. - Returns None if there are no outputs (e.g. a settings-only 'none' type - target).""" - - self.config_name = config_name - self.name = spec['target_name'] - self.toolset = spec['toolset'] - config = spec['configurations'][config_name] - self.target = Target(spec['type']) - self.is_standalone_static_library = bool( - spec.get('standalone_static_library', 0)) - - self.target_rpath = generator_flags.get('target_rpath', r'\$$ORIGIN/lib/') - - self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec) - self.xcode_settings = self.msvs_settings = None - if self.flavor == 'mac': - self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec) - mac_toolchain_dir = generator_flags.get('mac_toolchain_dir', None) - if mac_toolchain_dir: - self.xcode_settings.mac_toolchain_dir = mac_toolchain_dir - - if self.flavor == 'win': - self.msvs_settings = gyp.msvs_emulation.MsvsSettings(spec, - generator_flags) - arch = self.msvs_settings.GetArch(config_name) - 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) - if len(self.archs) > 1: - self.arch_subninjas = dict( - (arch, ninja_syntax.Writer( - OpenOutput(os.path.join(self.toplevel_build, - self._SubninjaNameForArch(arch)), - 'w'))) - for arch in self.archs) - - # Compute predepends for all rules. - # actions_depends is the dependencies this target depends on before running - # any of its action/rule/copy steps. - # compile_depends is the dependencies this target depends on before running - # any of its compile steps. - actions_depends = [] - compile_depends = [] - # TODO(evan): it is rather confusing which things are lists and which - # are strings. Fix these. - if 'dependencies' in spec: - for dep in spec['dependencies']: - if dep in self.target_outputs: - target = self.target_outputs[dep] - actions_depends.append(target.PreActionInput(self.flavor)) - compile_depends.append(target.PreCompileInput()) - if target.uses_cpp: - self.target.uses_cpp = True - actions_depends = filter(None, actions_depends) - compile_depends = filter(None, compile_depends) - actions_depends = self.WriteCollapsedDependencies('actions_depends', - actions_depends) - compile_depends = self.WriteCollapsedDependencies('compile_depends', - compile_depends) - self.target.preaction_stamp = actions_depends - self.target.precompile_stamp = compile_depends - - # Write out actions, rules, and copies. These must happen before we - # compile any sources, so compute a list of predependencies for sources - # while we do it. - extra_sources = [] - mac_bundle_depends = [] - self.target.actions_stamp = self.WriteActionsRulesCopies( - spec, extra_sources, actions_depends, mac_bundle_depends) - - # If we have actions/rules/copies, we depend directly on those, but - # otherwise we depend on dependent target's actions/rules/copies etc. - # We never need to explicitly depend on previous target's link steps, - # because no compile ever depends on them. - compile_depends_stamp = (self.target.actions_stamp or compile_depends) - - # Write out the compilation steps, if any. - link_deps = [] - try: - sources = extra_sources + spec.get('sources', []) - except TypeError: - print 'extra_sources: ', str(extra_sources) - print 'spec.get("sources"): ', str(spec.get('sources')) - raise - if sources: - if self.flavor == 'mac' and len(self.archs) > 1: - # Write subninja file containing compile and link commands scoped to - # a single arch if a fat binary is being built. - for arch in self.archs: - self.ninja.subninja(self._SubninjaNameForArch(arch)) - - pch = None - if self.flavor == 'win': - gyp.msvs_emulation.VerifyMissingSources( - sources, self.abs_build_dir, generator_flags, self.GypPathToNinja) - pch = gyp.msvs_emulation.PrecompiledHeader( - self.msvs_settings, config_name, self.GypPathToNinja, - self.GypPathToUniqueOutput, self.obj_ext) - else: - pch = gyp.xcode_emulation.MacPrefixHeader( - self.xcode_settings, self.GypPathToNinja, - lambda path, lang: self.GypPathToUniqueOutput(path + '-' + lang)) - link_deps = self.WriteSources( - self.ninja, config_name, config, sources, compile_depends_stamp, pch, - spec) - # Some actions/rules output 'sources' that are already object files. - obj_outputs = [f for f in sources if f.endswith(self.obj_ext)] - if obj_outputs: - if self.flavor != 'mac' or len(self.archs) == 1: - link_deps += [self.GypPathToNinja(o) for o in obj_outputs] - 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) - - compile_deps = self.target.actions_stamp or actions_depends - if self.flavor == 'win' and self.target.type == 'static_library': - self.target.component_objs = link_deps - self.target.compile_deps = compile_deps - - # Write out a link step, if needed. - output = None - is_empty_bundle = not link_deps and not mac_bundle_depends - if link_deps or self.target.actions_stamp or actions_depends: - output = self.WriteTarget(spec, config_name, config, link_deps, - compile_deps) - if self.is_mac_bundle: - mac_bundle_depends.append(output) - - # Bundle all of the above together, if needed. - if self.is_mac_bundle: - output = self.WriteMacBundle(spec, mac_bundle_depends, is_empty_bundle) - - if not output: - return None - - assert self.target.FinalOutput(), output - return self.target - - def _WinIdlRule(self, source, prebuild, outputs): - """Handle the implicit VS .idl rule for one source file. Fills |outputs| - with files that are generated.""" - outdir, output, vars, flags = self.msvs_settings.GetIdlBuildData( - source, self.config_name) - outdir = self.GypPathToNinja(outdir) - def fix_path(path, rel=None): - path = os.path.join(outdir, path) - dirname, basename = os.path.split(source) - root, ext = os.path.splitext(basename) - path = self.ExpandRuleVariables( - path, root, dirname, source, ext, basename) - if rel: - path = os.path.relpath(path, rel) - return path - vars = [(name, fix_path(value, outdir)) for name, value in vars] - output = [fix_path(p) for p in output] - vars.append(('outdir', outdir)) - vars.append(('idlflags', flags)) - input = self.GypPathToNinja(source) - self.ninja.build(output, 'idl', input, - variables=vars, order_only=prebuild) - outputs.extend(output) - - def WriteWinIdlFiles(self, spec, prebuild): - """Writes rules to match MSVS's implicit idl handling.""" - assert self.flavor == 'win' - if self.msvs_settings.HasExplicitIdlRulesOrActions(spec): - return [] - outputs = [] - for source in filter(lambda x: x.endswith('.idl'), spec['sources']): - self._WinIdlRule(source, prebuild, outputs) - return outputs - - def WriteActionsRulesCopies(self, spec, extra_sources, prebuild, - mac_bundle_depends): - """Write out the Actions, Rules, and Copies steps. Return a path - representing the outputs of these steps.""" - outputs = [] - if self.is_mac_bundle: - mac_bundle_resources = spec.get('mac_bundle_resources', [])[:] - else: - mac_bundle_resources = [] - extra_mac_bundle_resources = [] - - if 'actions' in spec: - outputs += self.WriteActions(spec['actions'], extra_sources, prebuild, - extra_mac_bundle_resources) - if 'rules' in spec: - outputs += self.WriteRules(spec['rules'], extra_sources, prebuild, - mac_bundle_resources, - extra_mac_bundle_resources) - if 'copies' in spec: - outputs += self.WriteCopies(spec['copies'], prebuild, mac_bundle_depends) - - if 'sources' in spec and self.flavor == 'win': - outputs += self.WriteWinIdlFiles(spec, prebuild) - - if self.xcode_settings and self.xcode_settings.IsIosFramework(): - self.WriteiOSFrameworkHeaders(spec, outputs, prebuild) - - stamp = self.WriteCollapsedDependencies('actions_rules_copies', outputs) - - if self.is_mac_bundle: - 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 - - def GenerateDescription(self, verb, message, fallback): - """Generate and return a description of a build step. - - |verb| is the short summary, e.g. ACTION or RULE. - |message| is a hand-written description, or None if not available. - |fallback| is the gyp-level name of the step, usable as a fallback. - """ - if self.toolset != 'target': - verb += '(%s)' % self.toolset - if message: - return '%s %s' % (verb, self.ExpandSpecial(message)) - else: - return '%s %s: %s' % (verb, self.name, fallback) - - def WriteActions(self, actions, extra_sources, prebuild, - extra_mac_bundle_resources): - # Actions cd into the base directory. - env = self.GetToolchainEnv() - all_outputs = [] - for action in actions: - # First write out a rule for the action. - 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, pool, - depfile=depfile) - - inputs = [self.GypPathToNinja(i, env) for i in action['inputs']] - if int(action.get('process_outputs_as_sources', False)): - extra_sources += action['outputs'] - if int(action.get('process_outputs_as_mac_bundle_resources', False)): - extra_mac_bundle_resources += action['outputs'] - outputs = [self.GypPathToNinja(o, env) for o in action['outputs']] - - # Then write out an edge using the rule. - self.ninja.build(outputs, rule_name, inputs, - order_only=prebuild) - all_outputs += outputs - - self.ninja.newline() - - return all_outputs - - def WriteRules(self, rules, extra_sources, prebuild, - mac_bundle_resources, extra_mac_bundle_resources): - env = self.GetToolchainEnv() - all_outputs = [] - for rule in rules: - # 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', - rule.get('message', None), - ('%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, pool) - - # TODO: if the command references the outputs directly, we should - # simplify it to just use $out. - - # Rules can potentially make use of some special variables which - # must vary per source file. - # Compute the list of variables we'll need to provide. - special_locals = ('source', 'root', 'dirname', 'ext', 'name') - needed_variables = set(['source']) - for argument in args: - for var in special_locals: - if '${%s}' % var in argument: - needed_variables.add(var) - needed_variables = sorted(needed_variables) - - 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 sources: - source = os.path.normpath(source) - dirname, basename = os.path.split(source) - root, ext = os.path.splitext(basename) - - # Gather the list of inputs and outputs, expanding $vars if possible. - outputs = [self.ExpandRuleVariables(o, root, dirname, - source, ext, basename) - for o in rule['outputs']] - - if int(rule.get('process_outputs_as_sources', False)): - extra_sources += outputs - - was_mac_bundle_resource = source in mac_bundle_resources - if was_mac_bundle_resource or \ - int(rule.get('process_outputs_as_mac_bundle_resources', False)): - extra_mac_bundle_resources += outputs - # Note: This is n_resources * n_outputs_in_rule. Put to-be-removed - # items in a set and remove them all in a single pass if this becomes - # a performance issue. - if was_mac_bundle_resource: - mac_bundle_resources.remove(source) - - extra_bindings = [] - for var in needed_variables: - if var == 'root': - extra_bindings.append(('root', cygwin_munge(root))) - elif var == 'dirname': - # '$dirname' is a parameter to the rule action, which means - # it shouldn't be converted to a Ninja path. But we don't - # want $!PRODUCT_DIR in there either. - dirname_expanded = self.ExpandSpecial(dirname, self.base_to_build) - extra_bindings.append(('dirname', cygwin_munge(dirname_expanded))) - elif var == 'source': - # '$source' is a parameter to the rule action, which means - # it shouldn't be converted to a Ninja path. But we don't - # want $!PRODUCT_DIR in there either. - source_expanded = self.ExpandSpecial(source, self.base_to_build) - extra_bindings.append(('source', cygwin_munge(source_expanded))) - elif var == 'ext': - extra_bindings.append(('ext', ext)) - elif var == 'name': - extra_bindings.append(('name', cygwin_munge(basename))) - else: - assert var == None, repr(var) - - outputs = [self.GypPathToNinja(o, env) for o in outputs] - 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, - variables=extra_bindings) - - all_outputs.extend(outputs) - - return all_outputs - - def WriteCopies(self, copies, prebuild, mac_bundle_depends): - outputs = [] - if self.xcode_settings: - extra_env = self.xcode_settings.GetPerTargetSettings() - env = self.GetToolchainEnv(additional_settings=extra_env) - else: - env = self.GetToolchainEnv() - for copy in copies: - for path in copy['files']: - # Normalize the path so trailing slashes don't confuse us. - path = os.path.normpath(path) - basename = os.path.split(path)[1] - src = self.GypPathToNinja(path, env) - dst = self.GypPathToNinja(os.path.join(copy['destination'], basename), - env) - outputs += self.ninja.build(dst, 'copy', src, order_only=prebuild) - if self.is_mac_bundle: - # gyp has mac_bundle_resources to copy things into a bundle's - # Resources folder, but there's no built-in way to copy files to other - # places in the bundle. Hence, some targets use copies for this. Check - # if this file is copied into the current bundle, and if so add it to - # the bundle depends so that dependent targets get rebuilt if the copy - # input changes. - if dst.startswith(self.xcode_settings.GetBundleContentsFolderPath()): - mac_bundle_depends.append(dst) - - return outputs - - def WriteiOSFrameworkHeaders(self, spec, outputs, prebuild): - """Prebuild steps to generate hmap files and copy headers to destination.""" - framework = self.ComputeMacBundleOutput() - all_sources = spec['sources'] - copy_headers = spec['mac_framework_headers'] - output = self.GypPathToUniqueOutput('headers.hmap') - self.xcode_settings.header_map_path = output - all_headers = map(self.GypPathToNinja, - filter(lambda x:x.endswith(('.h')), all_sources)) - variables = [('framework', framework), - ('copy_headers', map(self.GypPathToNinja, copy_headers))] - outputs.extend(self.ninja.build( - output, 'compile_ios_framework_headers', all_headers, - variables=variables, order_only=prebuild)) - - def WriteMacBundleResources(self, resources, bundle_depends): - """Writes ninja edges for 'mac_bundle_resources'.""" - xcassets = [] - - extra_env = self.xcode_settings.GetPerTargetSettings() - env = self.GetSortedXcodeEnv(additional_settings=extra_env) - env = self.ComputeExportEnvString(env) - isBinary = self.xcode_settings.IsBinaryOutputFormat(self.config_name) - - for output, res in gyp.xcode_emulation.GetMacBundleResources( - generator_default_variables['PRODUCT_DIR'], - self.xcode_settings, map(self.GypPathToNinja, resources)): - output = self.ExpandSpecial(output) - if os.path.splitext(output)[-1] != '.xcassets': - self.ninja.build(output, 'mac_tool', res, - variables=[('mactool_cmd', 'copy-bundle-resource'), \ - ('env', env), ('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, 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'], - self.xcode_settings, self.GypPathToNinja) - if not info_plist: - return - out = self.ExpandSpecial(out) - if defines: - # Create an intermediate file to store preprocessed results. - 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, 'preprocess_infoplist', info_plist, - variables=[('defines',defines)]) - - env = self.GetSortedXcodeEnv(additional_settings=extra_env) - env = self.ComputeExportEnvString(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, - precompiled_header, spec): - """Write build rules to compile all of |sources|.""" - if self.toolset == 'host': - self.ninja.variable('ar', '$ar_host') - self.ninja.variable('cc', '$cc_host') - 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( - self.ninja, config_name, config, sources, predepends, - precompiled_header, spec) - else: - return dict((arch, self.WriteSourcesForArch( - self.arch_subninjas[arch], config_name, config, sources, predepends, - precompiled_header, spec, arch=arch)) - for arch in self.archs) - - def WriteSourcesForArch(self, ninja_file, config_name, config, sources, - predepends, precompiled_header, spec, arch=None): - """Write build rules to compile all of |sources|.""" - - extra_defines = [] - if self.flavor == 'mac': - cflags = self.xcode_settings.GetCflags(config_name, arch=arch) - cflags_c = self.xcode_settings.GetCflagsC(config_name) - cflags_cc = self.xcode_settings.GetCflagsCC(config_name) - cflags_objc = ['$cflags_c'] + \ - self.xcode_settings.GetCflagsObjC(config_name) - 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) - # 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_c: - obj = 'obj' - if self.toolset != 'target': - obj += '.' + self.toolset - 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', []) - cflags_c = config.get('cflags_c', []) - cflags_cc = config.get('cflags_cc', []) - - # Respect environment variables related to build, but target-specific - # flags can still override them. - if self.toolset == 'target': - cflags_c = (os.environ.get('CPPFLAGS', '').split() + - os.environ.get('CFLAGS', '').split() + cflags_c) - cflags_cc = (os.environ.get('CPPFLAGS', '').split() + - os.environ.get('CXXFLAGS', '').split() + cflags_cc) - elif self.toolset == 'host': - cflags_c = (os.environ.get('CPPFLAGS_host', '').split() + - os.environ.get('CFLAGS_host', '').split() + cflags_c) - cflags_cc = (os.environ.get('CPPFLAGS_host', '').split() + - os.environ.get('CXXFLAGS_host', '').split() + cflags_cc) - - defines = config.get('defines', []) + extra_defines - 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) - 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. - for ext, var in [('c', 'cflags_pch_c'), ('cc', 'cflags_pch_cc'), - ('m', 'cflags_pch_objc'), ('mm', 'cflags_pch_objcc')]: - 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', - map(self.ExpandSpecial, cflags_c)) - self.WriteVariableList(ninja_file, 'cflags_cc', - map(self.ExpandSpecial, cflags_cc)) - if self.flavor == 'mac': - self.WriteVariableList(ninja_file, 'cflags_objc', - 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:] - obj_ext = self.obj_ext - if ext in ('cc', 'cpp', 'cxx'): - command = 'cxx' - self.target.uses_cpp = True - elif ext == 'c' or (ext == 'S' and self.flavor != 'win'): - command = 'cc' - elif ext == 's' and self.flavor != 'win': # Doesn't generate .o.d files. - command = 'cc_s' - elif (self.flavor == 'win' and ext == 'asm' and - not self.msvs_settings.HasExplicitAsmRules(spec)): - command = 'asm' - # Add the _asm suffix as msvs is capable of handling .cc and - # .asm files of the same name without collision. - obj_ext = '_asm.obj' - elif self.flavor == 'mac' and ext == 'm': - command = 'objc' - elif self.flavor == 'mac' and ext == 'mm': - command = 'objcxx' - self.target.uses_cpp = True - elif self.flavor == 'win' and ext == 'rc': - command = 'rc' - obj_ext = '.res' - has_rc_source = True - else: - # Ignore unhandled extensions. - continue - input = self.GypPathToNinja(source) - output = self.GypPathToUniqueOutput(filename + obj_ext) - if arch is not None: - output = AddArch(output, arch) - implicit = precompiled_header.GetObjDependencies([input], [output], arch) - variables = [] - if self.flavor == 'win': - variables, output, implicit = precompiled_header.GetFlagsModifications( - input, output, implicit, command, cflags_c, cflags_cc, - self.ExpandSpecial) - ninja_file.build(output, command, input, - implicit=[gch for _, _, gch in implicit], - 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() - return outputs - - def WritePchTargets(self, ninja_file, pch_commands): - """Writes ninja rules to compile prefix headers.""" - if not pch_commands: - return - - for gch, lang_flag, lang, input in pch_commands: - var_name = { - 'c': 'cflags_pch_c', - 'cc': 'cflags_pch_cc', - 'm': 'cflags_pch_objc', - 'mm': 'cflags_pch_objcc', - }[lang] - - map = { 'c': 'cc', 'cc': 'cxx', 'm': 'objc', 'mm': 'objcxx', } - cmd = map.get(lang) - ninja_file.build(gch, cmd, input, variables=[(var_name, lang_flag)]) - - def WriteLink(self, spec, config_name, config, link_deps, compile_deps): - """Write out a link step. Fills out target.binary. """ - if self.flavor != 'mac' or len(self.archs) == 1: - return self.WriteLinkForArch( - self.ninja, spec, config_name, config, link_deps, compile_deps) - else: - output = self.ComputeOutput(spec) - inputs = [self.WriteLinkForArch(self.arch_subninjas[arch], spec, - config_name, config, link_deps[arch], - compile_deps, 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) - - # 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, - link_deps, compile_deps, arch=None): - """Write out a link step. Fills out target.binary. """ - command = { - 'executable': 'link', - 'loadable_module': 'solink_module', - 'shared_library': 'solink', - }[spec['type']] - command_suffix = '' - - implicit_deps = set() - solibs = set() - order_deps = set() - - if compile_deps: - # Normally, the compiles of the target already depend on compile_deps, - # but a shared_library target might have no sources and only link together - # a few static_library deps, so the link step also needs to depend - # on compile_deps to make sure actions in the shared_library target - # get run before the link. - order_deps.add(compile_deps) - - if 'dependencies' in spec: - # Two kinds of dependencies: - # - Linkable dependencies (like a .a or a .so): add them to the link line. - # - Non-linkable dependencies (like a rule that generates a file - # and writes a stamp file): add them to implicit_deps - extra_link_deps = set() - for dep in spec['dependencies']: - target = self.target_outputs.get(dep) - if not target: - continue - linkable = target.Linkable() - if linkable: - new_deps = [] - if (self.flavor == 'win' and - target.component_objs and - self.msvs_settings.IsUseLibraryDependencyInputs(config_name)): - new_deps = target.component_objs - if target.compile_deps: - order_deps.add(target.compile_deps) - elif self.flavor == 'win' and target.import_lib: - new_deps = [target.import_lib] - elif target.UsesToc(self.flavor): - solibs.add(target.binary) - implicit_deps.add(target.binary + '.TOC') - else: - 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) - - extra_bindings = [] - if self.target.uses_cpp and self.flavor != 'win': - extra_bindings.append(('ld', '$ldxx')) - - output = self.ComputeOutput(spec, arch) - if arch is None and not self.is_mac_bundle: - 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_base_name = self.GypPathToUniqueOutput( - self.ComputeOutputFileName(spec)) - 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)) - 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 = env_ldflags + config.get('ldflags', []) - if is_executable and len(solibs): - rpath = 'lib/' - if self.toolset != 'target': - rpath += self.toolset - ldflags.append(r'-Wl,-rpath=\$$ORIGIN/%s' % rpath) - else: - ldflags.append('-Wl,-rpath=%s' % self.target_rpath) - ldflags.append('-Wl,-rpath-link=%s' % rpath) - self.WriteVariableList(ninja_file, '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 = ['/LIBPATH:' + QuoteShellArgument(self.GypPathToNinja(l), - self.flavor) - for l in library_dirs] - else: - library_dirs = [QuoteShellArgument('-L' + self.GypPathToNinja(l), - self.flavor) - for l in library_dirs] - - libraries = gyp.common.uniquer(map(self.ExpandSpecial, - spec.get('libraries', []))) - if self.flavor == 'mac': - libraries = self.xcode_settings.AdjustLibraries(libraries, config_name) - elif self.flavor == 'win': - libraries = self.msvs_settings.AdjustLibraries(libraries) - - self.WriteVariableList(ninja_file, 'libs', library_dirs + libraries) - - linked_binary = output - - if command in ('solink', 'solink_module'): - 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(('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(sorted(solibs)))) - - ninja_file.build(output, command + command_suffix, link_deps, - implicit=sorted(implicit_deps), - order_only=list(order_deps), - variables=extra_bindings) - return linked_binary - - def WriteTarget(self, spec, config_name, config, link_deps, compile_deps): - extra_link_deps = any(self.target_outputs.get(dep).Linkable() - for dep in spec.get('dependencies', []) - if dep in self.target_outputs) - if spec['type'] == 'none' or (not link_deps and not extra_link_deps): - # TODO(evan): don't call this function for 'none' target types, as - # it doesn't do anything, and we fake out a 'binary' with a stamp file. - self.target.binary = compile_deps - self.target.type = 'none' - elif spec['type'] == 'static_library': - self.target.binary = self.ComputeOutput(spec) - if (self.flavor not in ('mac', 'openbsd', 'netbsd', 'win') and not - self.is_standalone_static_library): - self.ninja.build(self.target.binary, 'alink_thin', link_deps, - order_only=compile_deps) - else: - variables = [] - if self.xcode_settings: - libtool_flags = self.xcode_settings.GetLibtoolflags(config_name) - if libtool_flags: - variables.append(('libtool_flags', libtool_flags)) - if self.msvs_settings: - libflags = self.msvs_settings.GetLibFlags(config_name, - self.GypPathToNinja) - variables.append(('libflags', libflags)) - - if self.flavor != 'mac' or len(self.archs) == 1: - self.AppendPostbuildVariable(variables, spec, - self.target.binary, self.target.binary) - self.ninja.build(self.target.binary, 'alink', link_deps, - order_only=compile_deps, variables=variables) - else: - inputs = [] - for arch in self.archs: - output = self.ComputeOutput(spec, arch) - self.arch_subninjas[arch].build(output, 'alink', link_deps[arch], - order_only=compile_deps, - variables=variables) - inputs.append(output) - # TODO: It's not clear if libtool_flags should be passed to the alink - # call that combines single-arch .a files into a fat .a file. - self.AppendPostbuildVariable(variables, spec, - self.target.binary, self.target.binary) - self.ninja.build(self.target.binary, 'alink', inputs, - # FIXME: test proving order_only=compile_deps isn't - # needed. - variables=variables) - else: - self.target.binary = self.WriteLink(spec, config_name, config, link_deps, - compile_deps) - return self.target.binary - - def WriteMacBundle(self, spec, mac_bundle_depends, is_empty): - assert self.is_mac_bundle - package_framework = spec['type'] in ('shared_library', 'loadable_module') - output = self.ComputeMacBundleOutput() - if is_empty: - output += '.stamp' - variables = [] - self.AppendPostbuildVariable(variables, spec, output, self.target.binary, - is_command_start=not package_framework) - if package_framework and not is_empty: - if spec['type'] == 'shared_library' and self.xcode_settings.isIOS: - self.ninja.build(output, 'package_ios_framework', mac_bundle_depends, - variables=variables) - else: - variables.append(('version', self.xcode_settings.GetFrameworkVersion())) - self.ninja.build(output, 'package_framework', mac_bundle_depends, - variables=variables) - else: - self.ninja.build(output, 'stamp', mac_bundle_depends, - variables=variables) - 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 - abs_build_dir = self.abs_build_dir - return gyp.xcode_emulation.GetSortedXcodeEnv( - self.xcode_settings, abs_build_dir, - os.path.join(abs_build_dir, self.build_to_base), self.config_name, - additional_settings) - - def GetSortedXcodePostbuildEnv(self): - """Returns the variables Xcode would set for postbuild steps.""" - postbuild_settings = {} - # CHROMIUM_STRIP_SAVE_FILE is a chromium-specific hack. - # TODO(thakis): It would be nice to have some general mechanism instead. - strip_save_file = self.xcode_settings.GetPerTargetSetting( - 'CHROMIUM_STRIP_SAVE_FILE') - if strip_save_file: - postbuild_settings['CHROMIUM_STRIP_SAVE_FILE'] = strip_save_file - return self.GetSortedXcodeEnv(additional_settings=postbuild_settings) - - def AppendPostbuildVariable(self, variables, spec, output, binary, - is_command_start=False): - """Adds a 'postbuild' variable if there is a postbuild for |output|.""" - postbuild = self.GetPostbuildCommand(spec, output, binary, is_command_start) - if postbuild: - variables.append(('postbuilds', postbuild)) - - def GetPostbuildCommand(self, spec, output, output_binary, is_command_start): - """Returns a shell command that runs all the postbuilds, and removes - |output| if any of them fails. If |is_command_start| is False, then the - returned string will start with ' && '.""" - if not self.xcode_settings or spec['type'] == 'none' or not output: - return '' - output = QuoteShellArgument(output, self.flavor) - postbuilds = gyp.xcode_emulation.GetSpecPostbuildCommands(spec, quiet=True) - if output_binary is not None: - 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), - postbuilds, quiet=True) - - if not postbuilds: - return '' - # Postbuilds expect to be run in the gyp file's directory, so insert an - # implicit postbuild to cd to there. - postbuilds.insert(0, gyp.common.EncodePOSIXShellList( - ['cd', self.build_to_base])) - env = self.ComputeExportEnvString(self.GetSortedXcodePostbuildEnv()) - # G will be non-null if any postbuild fails. Run all postbuilds in a - # subshell. - commands = env + ' (' + \ - ' && '.join([ninja_syntax.escape(command) for command in postbuilds]) - command_string = (commands + '); G=$$?; ' - # Remove the final output if any postbuild failed. - '((exit $$G) || rm -rf %s) ' % output + '&& exit $$G)') - if is_command_start: - return '(' + command_string + ' && ' - else: - return '$ && (' + command_string - - def ComputeExportEnvString(self, env): - """Given an environment, returns a string looking like - 'export FOO=foo; export BAR="${FOO} bar;' - that exports |env| to the shell.""" - export_str = [] - for k, v in env: - export_str.append('export %s=%s;' % - (k, ninja_syntax.escape(gyp.common.EncodePOSIXShellArgument(v)))) - return ' '.join(export_str) - - def ComputeMacBundleOutput(self): - """Return the 'output' (full output path) to a bundle output directory.""" - assert self.is_mac_bundle - path = generator_default_variables['PRODUCT_DIR'] - return self.ExpandSpecial( - os.path.join(path, self.xcode_settings.GetWrapperName())) - - def ComputeOutputFileName(self, spec, type=None): - """Compute the filename of the final output for the current target.""" - if not type: - type = spec['type'] - - default_variables = copy.copy(generator_default_variables) - CalculateVariables(default_variables, {'flavor': self.flavor}) - - # Compute filename prefix: the product prefix, or a default for - # the product type. - DEFAULT_PREFIX = { - 'loadable_module': default_variables['SHARED_LIB_PREFIX'], - 'shared_library': default_variables['SHARED_LIB_PREFIX'], - 'static_library': default_variables['STATIC_LIB_PREFIX'], - 'executable': default_variables['EXECUTABLE_PREFIX'], - } - prefix = spec.get('product_prefix', DEFAULT_PREFIX.get(type, '')) - - # Compute filename extension: the product extension, or a default - # for the product type. - DEFAULT_EXTENSION = { - 'loadable_module': default_variables['SHARED_LIB_SUFFIX'], - 'shared_library': default_variables['SHARED_LIB_SUFFIX'], - 'static_library': default_variables['STATIC_LIB_SUFFIX'], - 'executable': default_variables['EXECUTABLE_SUFFIX'], - } - extension = spec.get('product_extension') - if extension: - extension = '.' + extension - else: - extension = DEFAULT_EXTENSION.get(type, '') - - if 'product_name' in spec: - # If we were given an explicit name, use that. - target = spec['product_name'] - else: - # Otherwise, derive a name from the target name. - target = spec['target_name'] - if prefix == 'lib': - # Snip out an extra 'lib' from libs if appropriate. - target = StripPrefix(target, 'lib') - - if type in ('static_library', 'loadable_module', 'shared_library', - 'executable'): - return '%s%s%s' % (prefix, target, extension) - elif type == 'none': - return '%s.stamp' % target - else: - raise Exception('Unhandled output type %s' % type) - - def ComputeOutput(self, spec, arch=None): - """Compute the path for the final output of the spec.""" - type = spec['type'] - - if self.flavor == 'win': - override = self.msvs_settings.GetOutputName(self.config_name, - self.ExpandSpecial) - if override: - return override - - if arch is None and self.flavor == 'mac' and type in ( - 'static_library', 'executable', 'shared_library', 'loadable_module'): - filename = self.xcode_settings.GetExecutablePath() - else: - filename = self.ComputeOutputFileName(spec, type) - - if arch is None and 'product_dir' in spec: - path = os.path.join(spec['product_dir'], filename) - return self.ExpandSpecial(path) - - # Some products go into the output root, libraries go into shared library - # dir, and everything else goes into the normal place. - type_in_output_root = ['executable', 'loadable_module'] - if self.flavor == 'mac' and self.toolset == 'target': - type_in_output_root += ['shared_library', 'static_library'] - elif self.flavor == 'win' and self.toolset == 'target': - type_in_output_root += ['shared_library'] - - if arch is not None: - # Make sure partial executables don't end up in a bundle or the regular - # output directory. - archdir = 'arch' - if self.toolset != 'target': - archdir = os.path.join('arch', '%s' % self.toolset) - return os.path.join(archdir, AddArch(filename, arch)) - elif type in type_in_output_root or self.is_standalone_static_library: - return filename - elif type == 'shared_library': - libdir = 'lib' - if self.toolset != 'target': - libdir = os.path.join('lib', '%s' % self.toolset) - return os.path.join(libdir, filename) - else: - return self.GypPathToUniqueOutput(filename, qualified=False) - - def WriteVariableList(self, ninja_file, var, values): - assert not isinstance(values, str) - if values is None: - values = [] - ninja_file.variable(var, ' '.join(values)) - - 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 - expanded.""" - - if self.flavor == 'win': - args = [self.msvs_settings.ConvertVSMacros( - arg, self.base_to_build, config=self.config_name) - for arg in args] - description = self.msvs_settings.ConvertVSMacros( - description, config=self.config_name) - elif self.flavor == 'mac': - # |env| is an empty list on non-mac. - args = [gyp.xcode_emulation.ExpandEnvVars(arg, env) for arg in args] - description = gyp.xcode_emulation.ExpandEnvVars(description, env) - - # TODO: we shouldn't need to qualify names; we do it because - # currently the ninja rule namespace is global, but it really - # should be scoped to the subninja. - rule_name = self.name - if self.toolset == 'target': - rule_name += '.' + self.toolset - rule_name += '.' + name - rule_name = re.sub('[^a-zA-Z0-9_]', '_', rule_name) - - # Remove variable references, but not if they refer to the magic rule - # variables. This is not quite right, as it also protects these for - # actions, not just for rules where they are valid. Good enough. - protect = [ '${root}', '${dirname}', '${source}', '${ext}', '${name}' ] - protect = '(?!' + '|'.join(map(re.escape, protect)) + ')' - description = re.sub(protect + r'\$', '_', description) - - # gyp dictates that commands are run from the base directory. - # cd into the directory before running, and adjust paths in - # the arguments to point to the proper locations. - rspfile = None - rspfile_content = None - args = [self.ExpandSpecial(arg, self.base_to_build) for arg in args] - if self.flavor == 'win': - rspfile = rule_name + '.$unique_name.rsp' - # The cygwin case handles this inside the bash sub-shell. - run_in = '' if is_cygwin else ' ' + self.build_to_base - if is_cygwin: - rspfile_content = self.msvs_settings.BuildCygwinBashCommandLine( - args, self.build_to_base) - else: - rspfile_content = gyp.msvs_emulation.EncodeRspFileList(args) - command = ('%s gyp-win-tool action-wrapper $arch ' % sys.executable + - rspfile + run_in) - else: - env = self.ComputeExportEnvString(env) - command = gyp.common.EncodePOSIXShellList(args) - command = 'cd %s; ' % self.build_to_base + env + command - - # 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, depfile=depfile, - restat=True, pool=pool, - rspfile=rspfile, rspfile_content=rspfile_content) - self.ninja.newline() - - return rule_name, args - - -def CalculateVariables(default_variables, params): - """Calculate additional variables for use in the build (called by gyp).""" - global generator_additional_non_configuration_keys - global generator_additional_path_sections - flavor = gyp.common.GetFlavor(params) - if flavor == 'mac': - default_variables.setdefault('OS', 'mac') - default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib') - default_variables.setdefault('SHARED_LIB_DIR', - generator_default_variables['PRODUCT_DIR']) - default_variables.setdefault('LIB_DIR', - generator_default_variables['PRODUCT_DIR']) - - # Copy additional generator configuration data from Xcode, which is shared - # by the Mac Ninja generator. - import gyp.generator.xcode as xcode_generator - generator_additional_non_configuration_keys = getattr(xcode_generator, - 'generator_additional_non_configuration_keys', []) - generator_additional_path_sections = getattr(xcode_generator, - 'generator_additional_path_sections', []) - global generator_extra_sources_for_rules - 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'] = '.' + exts['executable'] - default_variables['STATIC_LIB_PREFIX'] = '' - default_variables['STATIC_LIB_SUFFIX'] = '.' + exts['static_library'] - default_variables['SHARED_LIB_PREFIX'] = '' - default_variables['SHARED_LIB_SUFFIX'] = '.' + exts['shared_library'] - - # 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) - default_variables.setdefault('SHARED_LIB_SUFFIX', '.so') - default_variables.setdefault('SHARED_LIB_DIR', - os.path.join('$!PRODUCT_DIR', 'lib')) - 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.""" - gyp.common.EnsureDirExists(path) - return open(path, mode) - - -def CommandWithWrapper(cmd, wrappers, prog): - wrapper = wrappers.get(cmd, '') - if wrapper: - return wrapper + ' ' + prog - return prog - - -def GetDefaultConcurrentLinks(): - """Returns a best-guess for a number of concurrent links.""" - pool_size = int(os.environ.get('GYP_LINK_CONCURRENCY', 0)) - if pool_size: - return pool_size - - if sys.platform in ('win32', 'cygwin'): - import ctypes - - class MEMORYSTATUSEX(ctypes.Structure): - _fields_ = [ - ("dwLength", ctypes.c_ulong), - ("dwMemoryLoad", ctypes.c_ulong), - ("ullTotalPhys", ctypes.c_ulonglong), - ("ullAvailPhys", ctypes.c_ulonglong), - ("ullTotalPageFile", ctypes.c_ulonglong), - ("ullAvailPageFile", ctypes.c_ulonglong), - ("ullTotalVirtual", ctypes.c_ulonglong), - ("ullAvailVirtual", ctypes.c_ulonglong), - ("sullAvailExtendedVirtual", ctypes.c_ulonglong), - ] - - stat = MEMORYSTATUSEX() - stat.dwLength = ctypes.sizeof(stat) - ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat)) - - # 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.environ.get('GYP_LINK_CONCURRENCY_MAX', 2**32))) - return min(mem_limit, hard_cap) - elif sys.platform.startswith('linux'): - 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: - avail_bytes = int(subprocess.check_output(['sysctl', '-n', 'hw.memsize'])) - # A static library debug build of Chromium's unit_tests takes ~2.7GB, so - # 4GB per ld process allows for some more bloat. - return max(1, avail_bytes / (4 * (2 ** 30))) # total / 4GB - except: - return 1 - else: - # TODO(scottmg): Implement this for other platforms. - return 1 - - -def _GetWinLinkRuleNameSuffix(embed_manifest): - """Returns the suffix used to select an appropriate linking rule depending on - whether the manifest embedding is enabled.""" - return '_embed' if embed_manifest else '' - - -def _AddWinLinkRules(master_ninja, embed_manifest): - """Adds link rules for Windows platform to |master_ninja|.""" - def FullLinkCommand(ldcmd, out, binary_type): - resource_name = { - 'exe': '1', - 'dll': '2', - }[binary_type] - 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='$binary.rsp', - rspfile_content='$libs $in_newline $ldflags', - restat=True, - pool='link_pool') - master_ninja.rule('solink_module' + rule_name_suffix, - description=dlldesc, command=dllcmd, - rspfile='$binary.rsp', - rspfile_content='$libs $in_newline $ldflags', - 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 %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 $binary' % rule_name_suffix.upper(), - command=exe_cmd, - rspfile='$binary.rsp', - rspfile_content='$in_newline $libs $ldflags', - pool='link_pool') - - -def GenerateOutputForConfig(target_list, target_dicts, data, params, - config_name): - options = params['options'] - flavor = gyp.common.GetFlavor(params) - generator_flags = params.get('generator_flags', {}) - - # build_dir: relative path from source root to our output files. - # e.g. "out/Debug" - build_dir = os.path.normpath( - os.path.join(ComputeOutputDir(params), config_name)) - - toplevel_build = os.path.join(options.toplevel_dir, build_dir) - - 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, generator_flags) - - # Grab make settings for CC/CXX. - # The rules are - # - The priority from low to high is gcc/g++, the 'make_global_settings' in - # gyp, the environment variable. - # - If there is no 'make_global_settings' for CC.host/CXX.host or - # 'CC_host'/'CXX_host' enviroment variable, cc_host/cxx_host should be set - # to cc/cxx. - if flavor == 'win': - 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: - 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', []) - build_to_root = gyp.common.InvertRelativePath(build_dir, - 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': - cc_host = os.path.join(build_to_root, value) - cc_host_global_setting = value - 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 == 'LDXX': - ldxx = os.path.join(build_to_root, value) - if key == 'LDXX.host': - ldxx_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) - - # Support wrappers from environment variables too. - for key, value in os.environ.iteritems(): - if key.lower().endswith('_wrapper'): - key_prefix = key[:-len('_wrapper')] - key_prefix = re.sub(r'\.HOST$', '.host', key_prefix) - wrappers[key_prefix] = os.path.join(build_to_root, value) - - mac_toolchain_dir = generator_flags.get('mac_toolchain_dir', None) - if mac_toolchain_dir: - wrappers['LINK'] = "export DEVELOPER_DIR='%s' &&" % mac_toolchain_dir - - 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, shared_system_includes, OpenOutput) - for arch, path in sorted(cl_paths.iteritems()): - 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)) - cxx = GetEnvironFallback(['CXX_target', 'CXX'], cxx) - master_ninja.variable('cxx', CommandWithWrapper('CXX', wrappers, cxx)) - - if flavor == 'win': - master_ninja.variable('ld', ld) - master_ninja.variable('idl', 'midl.exe') - master_ninja.variable('ar', ar) - master_ninja.variable('rc', 'rc.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)) - 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: - cc_host = cc - if not cxx_host: - cxx_host = cxx - - 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) - - # The environment variable could be used in 'make_global_settings', like - # ['CC.host', '$(CC)'] or ['CXX.host', '$(CXX)'], transform them here. - if '$(CC)' in cc_host and cc_host_global_setting: - cc_host = cc_host_global_setting.replace('$(CC)', cc) - if '$(CXX)' in cxx_host and cxx_host_global_setting: - cxx_host = cxx_host_global_setting.replace('$(CXX)', cxx) - master_ninja.variable('cc_host', - CommandWithWrapper('CC.host', wrappers, cc_host)) - master_ninja.variable('cxx_host', - CommandWithWrapper('CXX.host', wrappers, cxx_host)) - if flavor == 'win': - master_ninja.variable('ld_host', ld_host) - master_ninja.variable('ldxx_host', ldxx_host) - else: - master_ninja.variable('ld_host', CommandWithWrapper( - 'LINK', wrappers, ld_host)) - master_ninja.variable('ldxx_host', CommandWithWrapper( - 'LINK', wrappers, ldxx_host)) - - master_ninja.newline() - - master_ninja.pool('link_pool', depth=GetDefaultConcurrentLinks()) - master_ninja.newline() - - deps = 'msvc' if flavor == 'win' else 'gcc' - - if flavor != 'win': - master_ninja.rule( - 'cc', - description='CC $out', - command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c ' - '$cflags_pch_c -c $in -o $out'), - depfile='$out.d', - deps=deps) - master_ninja.rule( - 'cc_s', - description='CC $out', - command=('$cc $defines $includes $cflags $cflags_c ' - '$cflags_pch_c -c $in -o $out')) - master_ninja.rule( - 'cxx', - description='CXX $out', - command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc ' - '$cflags_pch_cc -c $in -o $out'), - 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_c ') - cxx_command = ('ninja -t msvc -e $arch ' + - '-- ' - '$cxx /nologo /showIncludes /FC ' - '@$out.rsp /c $in /Fo$out /Fd$pdbname_cc ') - master_ninja.rule( - 'cc', - description='CC $out', - command=cc_command, - rspfile='$out.rsp', - rspfile_content='$defines $includes $cflags $cflags_c', - deps=deps) - master_ninja.rule( - 'cxx', - description='CXX $out', - command=cxx_command, - rspfile='$out.rsp', - rspfile_content='$defines $includes $cflags $cflags_cc', - deps=deps) - master_ninja.rule( - 'idl', - description='IDL $in', - command=('%s gyp-win-tool midl-wrapper $arch $outdir ' - '$tlb $h $dlldata $iid $proxy $in ' - '$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 $resource_includes $rcflags /fo$out $in' % - sys.executable)) - master_ninja.rule( - 'asm', - description='ASM $out', - command=('%s gyp-win-tool asm-wrapper ' - '$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 $arflags $out $in') - master_ninja.rule( - 'alink_thin', - description='AR $out', - 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 - # dependencies when $lib changes only in non-public ways. - # 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 ; ' - '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\' \'; }')}) - - master_ninja.rule( - 'solink', - description='SOLINK $lib', - restat=True, - 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': '@$link_file_list'}, - rspfile='$link_file_list', - rspfile_content='-Wl,--start-group $in $solibs $libs -Wl,--end-group', - pool='link_pool') - master_ninja.rule( - 'link', - description='LINK $out', - command=('$ld $ldflags -o $out ' - '-Wl,--start-group $in $solibs $libs -Wl,--end-group'), - pool='link_pool') - elif flavor == 'win': - master_ninja.rule( - 'alink', - description='LIB $out', - 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) - _AddWinLinkRules(master_ninja, embed_manifest=False) - else: - master_ninja.rule( - 'objc', - description='OBJC $out', - command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_objc ' - '$cflags_pch_objc -c $in -o $out'), - depfile='$out.d', - deps=deps) - master_ninja.rule( - 'objcxx', - description='OBJCXX $out', - command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_objcc ' - '$cflags_pch_objcc -c $in -o $out'), - depfile='$out.d', - deps=deps) - master_ninja.rule( - 'alink', - description='LIBTOOL-STATIC $out, POSTBUILDS', - command='rm -f $out && ' - './gyp-mac-tool filter-libtool libtool $libtool_flags ' - '-static -o $out $in' - '$postbuilds') - master_ninja.rule( - '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 ] || ' - # 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; ' - 'else ' - '%(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, - 'extract_toc': - '{ otool -l $lib | grep LC_ID_DYLIB -A 5; ' - 'nm -gP $lib | cut -f1-2 -d\' \' | grep -v U$$; true; }'}) - - - 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') - - master_ninja.rule( - 'solink_module', - description='SOLINK(module) $lib, POSTBUILDS', - restat=True, - 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_suffix, 'type': '-bundle'}, - rspfile='$link_file_list', - rspfile_content='$in $solibs $libs', - pool='link_pool') - - master_ninja.rule( - 'link', - description='LINK $out, POSTBUILDS', - command=('$ld $ldflags -o $out ' - '$in $solibs $libs$postbuilds'), - pool='link_pool') - master_ninja.rule( - '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( - 'compile_ios_framework_headers', - description='COMPILE HEADER MAPS AND COPY FRAMEWORK HEADERS $in', - command='$env ./gyp-mac-tool compile-ios-framework-header-map $out ' - '$framework $in && $env ./gyp-mac-tool ' - 'copy-ios-framework-headers $framework $copy_headers') - master_ninja.rule( - 'mac_tool', - description='MACTOOL $mactool_cmd $in', - command='$env ./gyp-mac-tool $mactool_cmd $in $out $binary') - master_ninja.rule( - 'package_framework', - description='PACKAGE FRAMEWORK $out, POSTBUILDS', - command='./gyp-mac-tool package-framework $out $version$postbuilds ' - '&& touch $out') - master_ninja.rule( - 'package_ios_framework', - description='PACKAGE IOS FRAMEWORK $out, POSTBUILDS', - command='./gyp-mac-tool package-ios-framework $out $postbuilds ' - '&& touch $out') - if flavor == 'win': - master_ninja.rule( - 'stamp', - description='STAMP $out', - command='%s gyp-win-tool stamp $out' % sys.executable) - master_ninja.rule( - 'copy', - description='COPY $in $out', - command='%s gyp-win-tool recursive-mirror $in $out' % sys.executable) - else: - master_ninja.rule( - 'stamp', - description='STAMP $out', - command='${postbuilds}touch $out') - master_ninja.rule( - 'copy', - description='COPY $in $out', - command='ln -f $in $out 2>/dev/null || (rm -rf $out && cp -af $in $out)') - master_ninja.newline() - - all_targets = set() - for build_file in params['build_files']: - for target in gyp.common.AllTargets(target_list, - target_dicts, - os.path.normpath(build_file)): - all_targets.add(target) - all_outputs = set() - - # target_outputs is a map from qualified target name to a Target object. - target_outputs = {} - # target_short_names is a map from target short name to a list of Target - # objects. - target_short_names = {} - - # 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 - build_file, name, toolset = \ - gyp.common.ParseQualifiedTarget(qualified_target) - - 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. %s vs. %s" % - (this_make_global_settings, make_global_settings)) - - spec = target_dicts[qualified_target] - if flavor == 'mac': - gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec) - - # If build_file is a symlink, we must not follow it because there's a chance - # it could point to a path above toplevel_dir, and we cannot correctly deal - # with that case at the moment. - build_file = gyp.common.RelativePath(build_file, options.toplevel_dir, - False) - - 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': - obj += '.' + toolset - output_file = os.path.join(obj, base_path, name + '.ninja') - - ninja_output = StringIO() - writer = NinjaWriter(hash_for_rules, target_outputs, base_path, build_dir, - ninja_output, - toplevel_build, output_file, - flavor, toplevel_dir=options.toplevel_dir) - - target = writer.WriteSpec(spec, config_name, generator_flags) - - if ninja_output.tell() > 0: - # Only create files for ninja files that actually have contents. - with OpenOutput(os.path.join(toplevel_build, output_file)) as ninja_file: - ninja_file.write(ninja_output.getvalue()) - ninja_output.close() - master_ninja.subninja(output_file) - - if target: - if name != target.FinalOutput() and spec['toolset'] == 'target': - target_short_names.setdefault(name, []).append(target) - 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 - # "build chrome" case as well as the gyp tests, which expect to be - # able to run actions and build libraries by their short name. - master_ninja.newline() - master_ninja.comment('Short names for targets.') - for short_name in sorted(target_short_names): - 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', sorted(all_outputs)) - master_ninja.default(generator_flags.get('default_target', 'all')) - - master_ninja_file.close() - - -def PerformBuild(data, configurations, params): - options = params['options'] - for config in configurations: - builddir = os.path.join(options.toplevel_dir, 'out', config) - arguments = ['ninja', '-C', builddir] - print 'Building [%s]: %s' % (config, 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): - # 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) - target_list, target_dicts = MSVSUtil.InsertLargePdbShims( - target_list, target_dicts, generator_default_variables) - - 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 --git a/tools/gyp/pylib/gyp/generator/ninja_test.py b/tools/gyp/pylib/gyp/generator/ninja_test.py deleted file mode 100644 index 1767b2f45a04ca..00000000000000 --- a/tools/gyp/pylib/gyp/generator/ninja_test.py +++ /dev/null @@ -1,47 +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. - -""" Unit tests for the ninja.py file. """ - -import gyp.generator.ninja as ninja -import unittest -import StringIO -import sys -import TestCommon - - -class TestPrefixesAndSuffixes(unittest.TestCase): - def test_BinaryNamesWindows(self): - # 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', '.', - 'build.ninja', 'linux') - spec = { 'target_name': 'wee' } - self.assertTrue('.' not in writer.ComputeOutputFileName(spec, - 'executable')) - self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library'). - startswith('lib')) - self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library'). - startswith('lib')) - self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library'). - endswith('.so')) - self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library'). - endswith('.a')) - -if __name__ == '__main__': - unittest.main() diff --git a/tools/gyp/pylib/gyp/ordered_dict.py b/tools/gyp/pylib/gyp/ordered_dict.py deleted file mode 100644 index a1e89f9199087d..00000000000000 --- a/tools/gyp/pylib/gyp/ordered_dict.py +++ /dev/null @@ -1,289 +0,0 @@ -# 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 --git a/tools/gyp/pylib/gyp/xml_fix.py b/tools/gyp/pylib/gyp/xml_fix.py deleted file mode 100644 index 5de848158d2899..00000000000000 --- a/tools/gyp/pylib/gyp/xml_fix.py +++ /dev/null @@ -1,69 +0,0 @@ -# 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. - -"""Applies a fix to CR LF TAB handling in xml.dom. - -Fixes this: http://code.google.com/p/chromium/issues/detail?id=76293 -Working around this: http://bugs.python.org/issue5752 -TODO(bradnelson): Consider dropping this when we drop XP support. -""" - - -import xml.dom.minidom - - -def _Replacement_write_data(writer, data, is_attrib=False): - """Writes datachars to writer.""" - data = data.replace("&", "&").replace("<", "<") - data = data.replace("\"", """).replace(">", ">") - if is_attrib: - data = data.replace( - "\r", " ").replace( - "\n", " ").replace( - "\t", " ") - writer.write(data) - - -def _Replacement_writexml(self, writer, indent="", addindent="", newl=""): - # indent = current indentation - # addindent = indentation to add to higher levels - # newl = newline string - writer.write(indent+"<" + self.tagName) - - attrs = self._get_attributes() - a_names = attrs.keys() - a_names.sort() - - for a_name in a_names: - writer.write(" %s=\"" % a_name) - _Replacement_write_data(writer, attrs[a_name].value, is_attrib=True) - writer.write("\"") - if self.childNodes: - writer.write(">%s" % newl) - for node in self.childNodes: - node.writexml(writer, indent + addindent, addindent, newl) - writer.write("%s%s" % (indent, self.tagName, newl)) - else: - writer.write("/>%s" % newl) - - -class XmlFix(object): - """Object to manage temporary patching of xml.dom.minidom.""" - - def __init__(self): - # Preserve current xml.dom.minidom functions. - self.write_data = xml.dom.minidom._write_data - self.writexml = xml.dom.minidom.Element.writexml - # Inject replacement versions of a function and a method. - xml.dom.minidom._write_data = _Replacement_write_data - xml.dom.minidom.Element.writexml = _Replacement_writexml - - def Cleanup(self): - if self.write_data: - xml.dom.minidom._write_data = self.write_data - xml.dom.minidom.Element.writexml = self.writexml - self.write_data = None - - def __del__(self): - self.Cleanup() diff --git a/tools/gyp/samples/samples b/tools/gyp/samples/samples deleted file mode 100755 index 804b618998747d..00000000000000 --- a/tools/gyp/samples/samples +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/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 os.path -import shutil -import sys - - -gyps = [ - 'app/app.gyp', - 'base/base.gyp', - 'build/temp_gyp/googleurl.gyp', - 'build/all.gyp', - 'build/common.gypi', - 'build/external_code.gypi', - 'chrome/test/security_tests/security_tests.gyp', - 'chrome/third_party/hunspell/hunspell.gyp', - 'chrome/chrome.gyp', - 'media/media.gyp', - 'net/net.gyp', - 'printing/printing.gyp', - 'sdch/sdch.gyp', - 'skia/skia.gyp', - 'testing/gmock.gyp', - 'testing/gtest.gyp', - 'third_party/bzip2/bzip2.gyp', - 'third_party/icu38/icu38.gyp', - 'third_party/libevent/libevent.gyp', - 'third_party/libjpeg/libjpeg.gyp', - 'third_party/libpng/libpng.gyp', - 'third_party/libxml/libxml.gyp', - 'third_party/libxslt/libxslt.gyp', - 'third_party/lzma_sdk/lzma_sdk.gyp', - 'third_party/modp_b64/modp_b64.gyp', - 'third_party/npapi/npapi.gyp', - 'third_party/sqlite/sqlite.gyp', - 'third_party/zlib/zlib.gyp', - 'v8/tools/gyp/v8.gyp', - 'webkit/activex_shim/activex_shim.gyp', - 'webkit/activex_shim_dll/activex_shim_dll.gyp', - 'webkit/build/action_csspropertynames.py', - 'webkit/build/action_cssvaluekeywords.py', - 'webkit/build/action_jsconfig.py', - 'webkit/build/action_makenames.py', - 'webkit/build/action_maketokenizer.py', - 'webkit/build/action_useragentstylesheets.py', - 'webkit/build/rule_binding.py', - 'webkit/build/rule_bison.py', - 'webkit/build/rule_gperf.py', - 'webkit/tools/test_shell/test_shell.gyp', - 'webkit/webkit.gyp', -] - - -def Main(argv): - if len(argv) != 3 or argv[1] not in ['push', 'pull']: - print 'Usage: %s push/pull PATH_TO_CHROME' % argv[0] - return 1 - - path_to_chrome = argv[2] - - for g in gyps: - chrome_file = os.path.join(path_to_chrome, g) - local_file = os.path.join(os.path.dirname(argv[0]), os.path.split(g)[1]) - if argv[1] == 'push': - print 'Copying %s to %s' % (local_file, chrome_file) - shutil.copyfile(local_file, chrome_file) - elif argv[1] == 'pull': - print 'Copying %s to %s' % (chrome_file, local_file) - shutil.copyfile(chrome_file, local_file) - else: - assert False - - return 0 - - -if __name__ == '__main__': - sys.exit(Main(sys.argv)) diff --git a/tools/gyp/samples/samples.bat b/tools/gyp/samples/samples.bat deleted file mode 100644 index 778d9c90f06066..00000000000000 --- a/tools/gyp/samples/samples.bat +++ /dev/null @@ -1,5 +0,0 @@ -@rem Copyright (c) 2009 Google Inc. All rights reserved. -@rem Use of this source code is governed by a BSD-style license that can be -@rem found in the LICENSE file. - -@python %~dp0/samples %* diff --git a/tools/gyp/setup.cfg b/tools/gyp/setup.cfg new file mode 100644 index 00000000000000..20b3ca7f568c5f --- /dev/null +++ b/tools/gyp/setup.cfg @@ -0,0 +1,14 @@ +[metadata] +name = 'gyp3', +version = '6.0.0', +description = 'Generate You Projects 3', +author = 'Refael Ackermann', +author_email = 'refack@gmail.com', +url = 'https://gyp3.org', +package_dir = {'': 'lib'}, +packages = ['gyp', 'gyp.generator'], +entry_points = {'console_scripts': ['gyp=gyp:script_main']} + +[flake8] +exclude = .venv,out,testlib/SConsLib +select = E9,F8 diff --git a/tools/gyp/setup.py b/tools/gyp/setup.py deleted file mode 100755 index 75a42558d8026b..00000000000000 --- a/tools/gyp/setup.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/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. - -from setuptools import setup - -setup( - name='gyp', - version='0.1', - description='Generate Your Projects', - author='Chromium Authors', - author_email='chromium-dev@googlegroups.com', - url='http://code.google.com/p/gyp', - package_dir = {'': 'pylib'}, - packages=['gyp', 'gyp.generator'], - entry_points = {'console_scripts': ['gyp=gyp:script_main'] } -) diff --git a/tools/gyp/test/actions/bare/gyptest-bare.py b/tools/gyp/test/actions/bare/gyptest-bare.py new file mode 100644 index 00000000000000..e3d6db1029b39f --- /dev/null +++ b/tools/gyp/test/actions/bare/gyptest-bare.py @@ -0,0 +1,24 @@ +#!/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 actions which are not depended on by other targets get executed. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('bare.gyp', chdir='src') + +test.relocate('src', 'relocate/src') +test.build('bare.gyp', chdir='relocate/src') + +file_content = 'Hello from bare.py\n' + +test.built_file_must_match('out.txt', file_content, chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/actions/bare/src/bare.gyp b/tools/gyp/test/actions/bare/src/bare.gyp new file mode 100644 index 00000000000000..3d28f099d44789 --- /dev/null +++ b/tools/gyp/test/actions/bare/src/bare.gyp @@ -0,0 +1,25 @@ +# 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': 'bare', + 'type': 'none', + 'actions': [ + { + 'action_name': 'action1', + 'inputs': [ + 'bare.py', + ], + 'outputs': [ + '<(PRODUCT_DIR)/out.txt', + ], + 'action': ['python', 'bare.py', '<(PRODUCT_DIR)/out.txt'], + 'msvs_cygwin_shell': 0, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/actions/bare/src/bare.py b/tools/gyp/test/actions/bare/src/bare.py new file mode 100644 index 00000000000000..e153b774f9d527 --- /dev/null +++ b/tools/gyp/test/actions/bare/src/bare.py @@ -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 + +f = open(sys.argv[1], 'w') +f.write('Hello from bare.py\n') +f.close() diff --git a/tools/gyp/test/actions/depfile/depfile.gyp b/tools/gyp/test/actions/depfile/depfile.gyp new file mode 100644 index 00000000000000..dc2397de0544c7 --- /dev/null +++ b/tools/gyp/test/actions/depfile/depfile.gyp @@ -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 --git a/tools/gyp/test/actions/depfile/gyptest-all.py b/tools/gyp/test/actions/depfile/gyptest-all.py new file mode 100644 index 00000000000000..23f6f4a056707b --- /dev/null +++ b/tools/gyp/test/actions/depfile/gyptest-all.py @@ -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 --git a/tools/gyp/test/actions/depfile/input.txt b/tools/gyp/test/actions/depfile/input.txt new file mode 100644 index 00000000000000..3f9177e45e805c --- /dev/null +++ b/tools/gyp/test/actions/depfile/input.txt @@ -0,0 +1 @@ +input diff --git a/tools/gyp/test/actions/e2e/generated-header/action.py b/tools/gyp/test/actions/e2e/generated-header/action.py new file mode 100644 index 00000000000000..05e560ab28cdcc --- /dev/null +++ b/tools/gyp/test/actions/e2e/generated-header/action.py @@ -0,0 +1,10 @@ +#!/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. + +import sys + +outfile = sys.argv[1] +open(outfile, 'w').write('const char kFoo[] = "%s";' % sys.argv[2]) diff --git a/tools/gyp/test/actions/e2e/generated-header/main.cc b/tools/gyp/test/actions/e2e/generated-header/main.cc new file mode 100644 index 00000000000000..7973781bc6e500 --- /dev/null +++ b/tools/gyp/test/actions/e2e/generated-header/main.cc @@ -0,0 +1,7 @@ +#include + +#include "MyHeader.h" + +int main() { + printf("%s\n", kFoo); +} diff --git a/tools/gyp/test/actions/e2e/generated-header/test.gyp b/tools/gyp/test/actions/e2e/generated-header/test.gyp new file mode 100644 index 00000000000000..209b951ef6cb62 --- /dev/null +++ b/tools/gyp/test/actions/e2e/generated-header/test.gyp @@ -0,0 +1,34 @@ +# 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': 'generate_header', + 'type': 'none', + 'actions': [ + { + 'inputs': [ ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/MyHeader.h', + ], + 'action_name': 'generate header', + 'action': ['python', './action.py', + '<(SHARED_INTERMEDIATE_DIR)/MyHeader.h', 'foobar output' ], + }, + ], + 'msvs_cygwin_shell': 0, + }, + { + 'target_name': 'program', + 'type': 'executable', + 'dependencies': [ + 'generate_header', + ], + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + 'sources': [ 'main.cc' ], + }, + ], +} diff --git a/tools/gyp/test/actions/e2e/gyptest-all.py b/tools/gyp/test/actions/e2e/gyptest-all.py new file mode 100644 index 00000000000000..c8833a5d1ec458 --- /dev/null +++ b/tools/gyp/test/actions/e2e/gyptest-all.py @@ -0,0 +1,101 @@ +#!/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 simple actions when using an explicit build target of 'all'. +""" + +import glob +import os +import TestGyp + +test = TestGyp.TestGyp(workdir='workarea_all') + +test.run_gyp('actions.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +# Some gyp files use an action that mentions an output but never +# 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. +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 + # invocations, and that a dependent action updates in step. + test.build('actions.gyp', test.ALL, chdir='relocate/src') + test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '1') + test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '1') + test.build('actions.gyp', test.ALL, chdir='relocate/src') + test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '2') + test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '2') + + # The "always run" action only counts to 2, but the dependent target + # will count forever if it's allowed to run. This verifies that the + # dependent target only runs when the "always run" action generates + # new output, not just because the "always run" ran. + test.build('actions.gyp', test.ALL, chdir='relocate/src') + test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '2') + test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '2') + +expect = """\ +Hello from program.c +Hello from make-prog1.py +Hello from make-prog2.py +""" + +if test.format == 'xcode': + chdir = 'relocate/src/subdir1' +else: + chdir = 'relocate/src' +test.run_built_executable('program', chdir=chdir, stdout=expect) + + +test.must_match('relocate/src/subdir2/file.out', "Hello from make-file.py\n") + + +expect = "Hello from generate_main.py\n" + +if test.format == 'xcode': + chdir = 'relocate/src/subdir3' +else: + chdir = 'relocate/src' +test.run_built_executable('null_input', chdir=chdir, stdout=expect) + + +# Clean out files which may have been created if test.ALL was run. +def clean_dep_files(): + for file in (glob.glob('relocate/src/dep_*.txt') + + glob.glob('relocate/src/deps_all_done_*.txt')): + if os.path.exists(file): + os.remove(file) + +# Confirm our clean. +clean_dep_files() +test.must_not_exist('relocate/src/dep_1.txt') +test.must_not_exist('relocate/src/deps_all_done_first_123.txt') + +# Make sure all deps finish before an action is run on a 'None' target. +# If using the Make builder, add -j to make things more difficult. +arguments = [] +if test.format == 'make': + arguments = ['-j'] +test.build('actions.gyp', 'action_with_dependencies_123', chdir='relocate/src', + arguments=arguments) +test.must_exist('relocate/src/deps_all_done_first_123.txt') + +# Try again with a target that has deps in reverse. Output files from +# previous tests deleted. Confirm this execution did NOT run the ALL +# target which would mess up our dep tests. +clean_dep_files() +test.build('actions.gyp', 'action_with_dependencies_321', chdir='relocate/src', + arguments=arguments) +test.must_exist('relocate/src/deps_all_done_first_321.txt') +test.must_not_exist('relocate/src/deps_all_done_first_123.txt') + + +test.pass_test() diff --git a/tools/gyp/test/actions/e2e/gyptest-default.py b/tools/gyp/test/actions/e2e/gyptest-default.py new file mode 100644 index 00000000000000..70c99ec9ced687 --- /dev/null +++ b/tools/gyp/test/actions/e2e/gyptest-default.py @@ -0,0 +1,68 @@ +#!/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 simple actions when using the default build target. +""" + +import TestGyp + +test = TestGyp.TestGyp(workdir='workarea_default') + +test.run_gyp('actions.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +# Some gyp files use an action that mentions an output but never +# 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. +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 + # invocations, and that a dependent action updates in step. + test.build('actions.gyp', chdir='relocate/src') + test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '1') + test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '1') + test.build('actions.gyp', chdir='relocate/src') + test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '2') + test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '2') + + # The "always run" action only counts to 2, but the dependent target + # will count forever if it's allowed to run. This verifies that the + # dependent target only runs when the "always run" action generates + # new output, not just because the "always run" ran. + test.build('actions.gyp', test.ALL, chdir='relocate/src') + test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '2') + test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '2') + +expect = """\ +Hello from program.c +Hello from make-prog1.py +Hello from make-prog2.py +""" + +if test.format == 'xcode': + chdir = 'relocate/src/subdir1' +else: + chdir = 'relocate/src' +test.run_built_executable('program', chdir=chdir, stdout=expect) + + +test.must_match('relocate/src/subdir2/file.out', "Hello from make-file.py\n") + + +expect = "Hello from generate_main.py\n" + +if test.format == 'xcode': + chdir = 'relocate/src/subdir3' +else: + chdir = 'relocate/src' +test.run_built_executable('null_input', chdir=chdir, stdout=expect) + + +test.pass_test() diff --git a/tools/gyp/test/actions/e2e/gyptest-errors.py b/tools/gyp/test/actions/e2e/gyptest-errors.py new file mode 100644 index 00000000000000..158c24ad10e674 --- /dev/null +++ b/tools/gyp/test/actions/e2e/gyptest-errors.py @@ -0,0 +1,24 @@ +#!/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 behavior for different action configuration errors: +exit status of 1, and the expected error message must be in stderr. +""" + +import TestGyp + +test = TestGyp.TestGyp(workdir='workarea_errors') + + +test.run_gyp('action_missing_name.gyp', chdir='src', status=1, stderr=None) +expect = [ + "Anonymous action in target broken_actions2. An action must have an 'action_name' field.", +] +test.must_contain_all_lines(test.stderr(), expect) + + +test.pass_test() diff --git a/tools/gyp/test/actions/e2e/gyptest-generated-header.py b/tools/gyp/test/actions/e2e/gyptest-generated-header.py new file mode 100644 index 00000000000000..230ab7d7dc9cbf --- /dev/null +++ b/tools/gyp/test/actions/e2e/gyptest-generated-header.py @@ -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 dependencies on generated headers work, even if the header has +a mixed-case file name. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +CHDIR = 'generated-header' + +test.run_gyp('test.gyp', chdir=CHDIR) +test.build('test.gyp', 'program', chdir=CHDIR) +test.up_to_date('test.gyp', 'program', chdir=CHDIR) + +expect = 'foobar output\n' +test.run_built_executable('program', chdir=CHDIR, stdout=expect) + +# Change what's written to the generated header, regyp and rebuild, and check +# that the change makes it to the executable and that the build is clean. +test.sleep() +content = test.read('generated-header/test.gyp').replace('foobar', 'barbaz') +test.write('generated-header/test.gyp', content) + +test.run_gyp('test.gyp', chdir=CHDIR) +test.build('test.gyp', 'program', chdir=CHDIR) +test.up_to_date('test.gyp', 'program', chdir=CHDIR) + +expect = 'barbaz output\n' +test.run_built_executable('program', chdir=CHDIR, stdout=expect) + +test.pass_test() diff --git a/tools/gyp/test/actions/e2e/src/action_missing_name.gyp b/tools/gyp/test/actions/e2e/src/action_missing_name.gyp new file mode 100644 index 00000000000000..6647aac3b509ad --- /dev/null +++ b/tools/gyp/test/actions/e2e/src/action_missing_name.gyp @@ -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': 'broken_actions2', + 'type': 'none', + 'actions': [ + { + 'inputs': [ + 'no_name.input', + ], + 'action': [ + 'python', + '-c', + 'from __future__ import print_function; print(\'missing name\')', + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/actions/e2e/src/actions.gyp b/tools/gyp/test/actions/e2e/src/actions.gyp new file mode 100644 index 00000000000000..5d2db1955e2db1 --- /dev/null +++ b/tools/gyp/test/actions/e2e/src/actions.gyp @@ -0,0 +1,114 @@ +# 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': 'pull_in_all_actions', + 'type': 'none', + 'dependencies': [ + 'subdir1/executable.gyp:*', + 'subdir2/none.gyp:*', + 'subdir3/null_input.gyp:*', + ], + }, + { + 'target_name': 'depend_on_always_run_action', + 'type': 'none', + 'dependencies': [ 'subdir1/executable.gyp:counter' ], + 'actions': [ + { + 'action_name': 'use_always_run_output', + 'inputs': [ + 'subdir1/actions-out/action-counter.txt', + 'subdir1/counter.py', + ], + 'outputs': [ + 'subdir1/actions-out/action-counter_2.txt', + ], + 'action': [ + 'python', 'subdir1/counter.py', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + + # Three deps which don't finish immediately. + # Each one has a small delay then creates a file. + # Delays are 1.0, 1.1, and 2.0 seconds. + { + 'target_name': 'dep_1', + 'type': 'none', + 'actions': [{ + 'inputs': [ 'actions.gyp' ], + 'outputs': [ 'dep_1.txt' ], + 'action_name': 'dep_1', + 'action': [ 'python', '-c', + 'import time; time.sleep(1); open(\'dep_1.txt\', \'w\')' ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }], + }, + { + 'target_name': 'dep_2', + 'type': 'none', + 'actions': [{ + 'inputs': [ 'actions.gyp' ], + 'outputs': [ 'dep_2.txt' ], + 'action_name': 'dep_2', + 'action': [ 'python', '-c', + 'import time; time.sleep(1.1); open(\'dep_2.txt\', \'w\')' ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }], + }, + { + 'target_name': 'dep_3', + 'type': 'none', + 'actions': [{ + 'inputs': [ 'actions.gyp' ], + 'outputs': [ 'dep_3.txt' ], + 'action_name': 'dep_3', + 'action': [ 'python', '-c', + 'import time; time.sleep(2.0); open(\'dep_3.txt\', \'w\')' ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }], + }, + + # An action which assumes the deps have completed. + # Does NOT list the output files of it's deps as inputs. + # On success create the file deps_all_done_first.txt. + { + 'target_name': 'action_with_dependencies_123', + 'type': 'none', + 'dependencies': [ 'dep_1', 'dep_2', 'dep_3' ], + 'actions': [{ + 'inputs': [ 'actions.gyp' ], + 'outputs': [ 'deps_all_done_first_123.txt' ], + 'action_name': 'action_with_dependencies_123', + 'action': [ 'python', 'confirm-dep-files.py', '<(_outputs)' ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }], + }, + # Same as above but with deps in reverse. + { + 'target_name': 'action_with_dependencies_321', + 'type': 'none', + 'dependencies': [ 'dep_3', 'dep_2', 'dep_1' ], + 'actions': [{ + 'inputs': [ 'actions.gyp' ], + 'outputs': [ 'deps_all_done_first_321.txt' ], + 'action_name': 'action_with_dependencies_321', + 'action': [ 'python', 'confirm-dep-files.py', '<(_outputs)' ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }], + }, + + ], +} diff --git a/tools/gyp/test/actions/e2e/src/confirm-dep-files.py b/tools/gyp/test/actions/e2e/src/confirm-dep-files.py new file mode 100644 index 00000000000000..3b8463057df50d --- /dev/null +++ b/tools/gyp/test/actions/e2e/src/confirm-dep-files.py @@ -0,0 +1,21 @@ +#!/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. + +"""Confirms presence of files generated by our targets we depend on. +If they exist, create a new file. + +Note target's input files are explicitly NOT defined in the gyp file +so they can't easily be passed to this script as args. +""" + +import os +import sys + +outfile = sys.argv[1] # Example value we expect: deps_all_done_first_123.txt +if (os.path.exists("dep_1.txt") and + os.path.exists("dep_2.txt") and + os.path.exists("dep_3.txt")): + open(outfile, "w") diff --git a/tools/gyp/test/actions/e2e/src/subdir1/counter.py b/tools/gyp/test/actions/e2e/src/subdir1/counter.py new file mode 100644 index 00000000000000..d888f2e803bc94 --- /dev/null +++ b/tools/gyp/test/actions/e2e/src/subdir1/counter.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python + +# Copyright (c) 2010 Google 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 +import time + +output = sys.argv[1] +persistoutput = "%s.persist" % sys.argv[1] + +count = 0 +try: + count = open(persistoutput, 'r').read() +except: + pass +count = int(count) + 1 + +if len(sys.argv) > 2: + max_count = int(sys.argv[2]) + if count > max_count: + count = max_count + +oldcount = 0 +try: + oldcount = open(output, 'r').read() +except: + pass + +# Save the count in a file that is undeclared, and thus hidden, to gyp. We need +# to do this because, prior to running commands, some build systems deletes +# any declared outputs, so we would lose our count if we just wrote to the +# given output file. +open(persistoutput, 'w').write('%d' % (count)) + +# Only write the given output file if the count has changed. +if int(oldcount) != count: + open(output, 'w').write('%d' % (count)) + # Sleep so the next run changes the file time sufficiently to make the build + # detect the file as changed. + time.sleep(1) + +sys.exit(0) diff --git a/tools/gyp/test/actions/e2e/src/subdir1/executable.gyp b/tools/gyp/test/actions/e2e/src/subdir1/executable.gyp new file mode 100644 index 00000000000000..6a1ce4f91e0faa --- /dev/null +++ b/tools/gyp/test/actions/e2e/src/subdir1/executable.gyp @@ -0,0 +1,74 @@ +# 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': 'program', + 'type': 'executable', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'program.c', + ], + 'actions': [ + { + 'action_name': 'make-prog1', + 'inputs': [ + 'make-prog1.py', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/prog1.c', + ], + 'action': [ + 'python', '<(_inputs)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + { + 'action_name': 'make-prog2', + 'inputs': [ + 'make-prog2.py', + ], + 'outputs': [ + 'actions-out/prog2.c', + ], + 'action': [ + 'python', '<(_inputs)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + { + 'target_name': 'counter', + 'type': 'none', + 'actions': [ + { + # This action should always run, regardless of whether or not it's + # inputs or the command-line change. We do this by creating a dummy + # first output, which is always missing, thus causing the build to + # always try to recreate it. Actual output files should be listed + # after the dummy one, and dependent targets should list the real + # output(s) in their inputs + # (see '../actions.gyp:depend_on_always_run_action'). + 'action_name': 'action_counter', + 'inputs': [ + 'counter.py', + ], + 'outputs': [ + 'actions-out/action-counter.txt.always', + 'actions-out/action-counter.txt', + ], + 'action': [ + 'python', '<(_inputs)', 'actions-out/action-counter.txt', '2', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/actions/e2e/src/subdir1/make-prog1.py b/tools/gyp/test/actions/e2e/src/subdir1/make-prog1.py new file mode 100644 index 00000000000000..7ea1d8a2d48708 --- /dev/null +++ b/tools/gyp/test/actions/e2e/src/subdir1/make-prog1.py @@ -0,0 +1,20 @@ +#!/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 = r""" +#include + +void prog1(void) +{ + printf("Hello from make-prog1.py\n"); +} +""" + +open(sys.argv[1], 'w').write(contents) + +sys.exit(0) diff --git a/tools/gyp/test/actions/e2e/src/subdir1/make-prog2.py b/tools/gyp/test/actions/e2e/src/subdir1/make-prog2.py new file mode 100644 index 00000000000000..0bfe4973c24c15 --- /dev/null +++ b/tools/gyp/test/actions/e2e/src/subdir1/make-prog2.py @@ -0,0 +1,20 @@ +#!/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 = r""" +#include + +void prog2(void) +{ + printf("Hello from make-prog2.py\n"); +} +""" + +open(sys.argv[1], 'w').write(contents) + +sys.exit(0) diff --git a/tools/gyp/test/actions/e2e/src/subdir1/program.c b/tools/gyp/test/actions/e2e/src/subdir1/program.c new file mode 100644 index 00000000000000..15f0f94ee57f47 --- /dev/null +++ b/tools/gyp/test/actions/e2e/src/subdir1/program.c @@ -0,0 +1,12 @@ +#include + +extern void prog1(void); +extern void prog2(void); + +int main(void) +{ + printf("Hello from program.c\n"); + prog1(); + prog2(); + return 0; +} diff --git a/tools/gyp/test/actions/e2e/src/subdir2/make-file.py b/tools/gyp/test/actions/e2e/src/subdir2/make-file.py new file mode 100644 index 00000000000000..088a05e0b0cbca --- /dev/null +++ b/tools/gyp/test/actions/e2e/src/subdir2/make-file.py @@ -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 = "Hello from make-file.py\n" + +open(sys.argv[1], 'w').write(contents) diff --git a/tools/gyp/test/actions/e2e/src/subdir2/none.gyp b/tools/gyp/test/actions/e2e/src/subdir2/none.gyp new file mode 100644 index 00000000000000..2caa97d55c90e0 --- /dev/null +++ b/tools/gyp/test/actions/e2e/src/subdir2/none.gyp @@ -0,0 +1,33 @@ +# 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': 'file', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'actions': [ + { + 'action_name': 'make-file', + 'inputs': [ + 'make-file.py', + ], + 'outputs': [ + 'file.out', + # TODO: enhance testing infrastructure to test this + # without having to hard-code the intermediate dir paths. + #'<(INTERMEDIATE_DIR)/file.out', + ], + 'action': [ + 'python', '<(_inputs)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + } + ], + }, + ], +} diff --git a/tools/gyp/test/actions/e2e/src/subdir3/generate_main.py b/tools/gyp/test/actions/e2e/src/subdir3/generate_main.py new file mode 100644 index 00000000000000..804d38df3181ac --- /dev/null +++ b/tools/gyp/test/actions/e2e/src/subdir3/generate_main.py @@ -0,0 +1,21 @@ +#!/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 = """ +#include + +int main(void) +{ + printf("Hello from generate_main.py\\n"); + return 0; +} +""" + +open(sys.argv[1], 'w').write(contents) + +sys.exit(0) diff --git a/tools/gyp/test/actions/e2e/src/subdir3/null_input.gyp b/tools/gyp/test/actions/e2e/src/subdir3/null_input.gyp new file mode 100644 index 00000000000000..9b0bea5fdb40b8 --- /dev/null +++ b/tools/gyp/test/actions/e2e/src/subdir3/null_input.gyp @@ -0,0 +1,29 @@ +# 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': 'null_input', + 'type': 'executable', + 'msvs_cygwin_shell': 0, + 'actions': [ + { + 'action_name': 'generate_main', + 'process_outputs_as_sources': 1, + 'inputs': [], + 'outputs': [ + '<(INTERMEDIATE_DIR)/main.c', + ], + 'action': [ + # TODO: we can't just use <(_outputs) here?! + 'python', 'generate_main.py', '<(INTERMEDIATE_DIR)/main.c', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/actions/multiple-outputs-with-dependencies/gyptest-action.py b/tools/gyp/test/actions/multiple-outputs-with-dependencies/gyptest-action.py new file mode 100644 index 00000000000000..a9d218282cc1ab --- /dev/null +++ b/tools/gyp/test/actions/multiple-outputs-with-dependencies/gyptest-action.py @@ -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. + +""" +Verifies actions with multiple outputs & dependncies will correctly rebuild. + +This is a regression test for crrev.com/1177163002. +""" + +from __future__ import print_function + +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 --git a/tools/gyp/test/actions/multiple-outputs-with-dependencies/src/action.gyp b/tools/gyp/test/actions/multiple-outputs-with-dependencies/src/action.gyp new file mode 100644 index 00000000000000..a305d65ea9e68e --- /dev/null +++ b/tools/gyp/test/actions/multiple-outputs-with-dependencies/src/action.gyp @@ -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 --git a/tools/gyp/test/actions/multiple-outputs-with-dependencies/src/rcopy.py b/tools/gyp/test/actions/multiple-outputs-with-dependencies/src/rcopy.py new file mode 100644 index 00000000000000..34d1cd65ec1537 --- /dev/null +++ b/tools/gyp/test/actions/multiple-outputs-with-dependencies/src/rcopy.py @@ -0,0 +1,19 @@ +#!/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 + +"""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 --git a/tools/gyp/test/actions/multiple-outputs/gyptest-multiple-outputs.py b/tools/gyp/test/actions/multiple-outputs/gyptest-multiple-outputs.py new file mode 100644 index 00000000000000..5e2682d00ff6f0 --- /dev/null +++ b/tools/gyp/test/actions/multiple-outputs/gyptest-multiple-outputs.py @@ -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. + +""" +Verifies actions with multiple outputs will correctly rebuild. +""" + +from __future__ import print_function + +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 --git a/tools/gyp/test/actions/multiple-outputs/src/multiple-outputs.gyp b/tools/gyp/test/actions/multiple-outputs/src/multiple-outputs.gyp new file mode 100644 index 00000000000000..7a3d74b11ac08f --- /dev/null +++ b/tools/gyp/test/actions/multiple-outputs/src/multiple-outputs.gyp @@ -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 --git a/tools/gyp/test/actions/multiple-outputs/src/touch.py b/tools/gyp/test/actions/multiple-outputs/src/touch.py new file mode 100644 index 00000000000000..bc61267f39cea0 --- /dev/null +++ b/tools/gyp/test/actions/multiple-outputs/src/touch.py @@ -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 --git a/tools/gyp/test/actions/multiple/gyptest-all.py b/tools/gyp/test/actions/multiple/gyptest-all.py new file mode 100644 index 00000000000000..2a083de9b054a4 --- /dev/null +++ b/tools/gyp/test/actions/multiple/gyptest-all.py @@ -0,0 +1,72 @@ +#!/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 two actions can be attached to the same input files. +""" + +import sys + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('actions.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +# Test of fine-grained dependencies for generators that can build individual +# files on demand. +# In particular: +# - TargetA depends on TargetB. +# - TargetA and TargetB are 'none' type with actions attached. +# - TargetA has multiple actions. +# - An output from one of the actions in TargetA (not the first listed), +# is requested as the build target. +# Ensure that TargetB gets built. +# +# This sub-test can only be done with generators/build tools that can +# be asked to build individual files rather than whole targets (make, ninja). +if test.format in ['make', 'ninja']: + # Select location of target based on generator. + if test.format == 'make': + target = 'multi2.txt' + elif test.format == 'ninja': + if sys.platform in ['win32', 'cygwin']: + target = '..\\..\\multi2.txt' + else: + target = '../../multi2.txt' + else: + assert False + test.build('actions.gyp', chdir='relocate/src', target=target) + test.must_contain('relocate/src/multi2.txt', 'hello there') + test.must_contain('relocate/src/multi_dep.txt', 'hello there') + + +# Test that two actions can be attached to the same inputs. +test.build('actions.gyp', test.ALL, chdir='relocate/src') +test.must_contain('relocate/src/output1.txt', 'hello there') +test.must_contain('relocate/src/output2.txt', 'hello there') +test.must_contain('relocate/src/output3.txt', 'hello there') +test.must_contain('relocate/src/output4.txt', 'hello there') + +# Test that process_outputs_as_sources works in conjuction with merged +# actions. +test.run_built_executable( + 'multiple_action_source_filter', + chdir='relocate/src', + stdout=( + '{\n' + 'bar\n' + 'car\n' + 'dar\n' + 'ear\n' + '}\n' + ), +) + + +test.pass_test() diff --git a/tools/gyp/test/actions/multiple/src/actions.gyp b/tools/gyp/test/actions/multiple/src/actions.gyp new file mode 100644 index 00000000000000..d7423b589f912b --- /dev/null +++ b/tools/gyp/test/actions/multiple/src/actions.gyp @@ -0,0 +1,226 @@ +# 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. + +{ + 'variables': { + # Have a long string so that actions will exceed xp 512 character + # command limit on xp. + 'long_string': + 'abcdefghijklmnopqrstuvwxyz0123456789' + 'abcdefghijklmnopqrstuvwxyz0123456789' + 'abcdefghijklmnopqrstuvwxyz0123456789' + 'abcdefghijklmnopqrstuvwxyz0123456789' + 'abcdefghijklmnopqrstuvwxyz0123456789' + 'abcdefghijklmnopqrstuvwxyz0123456789' + 'abcdefghijklmnopqrstuvwxyz0123456789' + 'abcdefghijklmnopqrstuvwxyz0123456789' + 'abcdefghijklmnopqrstuvwxyz0123456789' + 'abcdefghijklmnopqrstuvwxyz0123456789' + 'abcdefghijklmnopqrstuvwxyz0123456789' + }, + 'targets': [ + { + 'target_name': 'multiple_action_target', + 'type': 'none', + 'actions': [ + { + 'action_name': 'action1', + 'inputs': [ + 'copyfile.py', + 'input.txt', + ], + 'outputs': [ + 'output1.txt', + ], + 'action': [ + 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + { + 'action_name': 'action2', + 'inputs': [ + 'copyfile.py', + 'input.txt', + ], + 'outputs': [ + 'output2.txt', + ], + 'action': [ + 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + { + 'action_name': 'action3', + 'inputs': [ + 'copyfile.py', + 'input.txt', + ], + 'outputs': [ + 'output3.txt', + ], + 'action': [ + 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + { + 'action_name': 'action4', + 'inputs': [ + 'copyfile.py', + 'input.txt', + ], + 'outputs': [ + 'output4.txt', + ], + 'action': [ + 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + { + 'target_name': 'multiple_action_source_filter', + 'type': 'executable', + 'sources': [ + 'main.c', + # TODO(bradnelson): add foo.c here once this issue is fixed: + # http://code.google.com/p/gyp/issues/detail?id=175 + ], + 'actions': [ + { + 'action_name': 'action1', + 'inputs': [ + 'foo.c', + 'filter.py', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/output1.c', + ], + 'process_outputs_as_sources': 1, + 'action': [ + 'python', 'filter.py', 'foo', 'bar', 'foo.c', '<@(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + { + 'action_name': 'action2', + 'inputs': [ + 'foo.c', + 'filter.py', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/output2.c', + ], + 'process_outputs_as_sources': 1, + 'action': [ + 'python', 'filter.py', 'foo', 'car', 'foo.c', '<@(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + { + 'action_name': 'action3', + 'inputs': [ + 'foo.c', + 'filter.py', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/output3.c', + ], + 'process_outputs_as_sources': 1, + 'action': [ + 'python', 'filter.py', 'foo', 'dar', 'foo.c', '<@(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + { + 'action_name': 'action4', + 'inputs': [ + 'foo.c', + 'filter.py', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/output4.c', + ], + 'process_outputs_as_sources': 1, + 'action': [ + 'python', 'filter.py', 'foo', 'ear', 'foo.c', '<@(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + { + 'target_name': 'multiple_dependent_target', + 'type': 'none', + 'actions': [ + { + 'action_name': 'action1', + 'inputs': [ + 'copyfile.py', + 'input.txt', + ], + 'outputs': [ + 'multi1.txt', + ], + 'action': [ + 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + { + 'action_name': 'action2', + 'inputs': [ + 'copyfile.py', + 'input.txt', + ], + 'outputs': [ + 'multi2.txt', + ], + 'action': [ + 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + 'dependencies': [ + 'multiple_required_target', + ], + }, + { + 'target_name': 'multiple_required_target', + 'type': 'none', + 'actions': [ + { + 'action_name': 'multi_dep', + 'inputs': [ + 'copyfile.py', + 'input.txt', + ], + 'outputs': [ + 'multi_dep.txt', + ], + 'process_outputs_as_sources': 1, + 'action': [ + 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/actions/multiple/src/copyfile.py b/tools/gyp/test/actions/multiple/src/copyfile.py new file mode 100644 index 00000000000000..07746793806493 --- /dev/null +++ b/tools/gyp/test/actions/multiple/src/copyfile.py @@ -0,0 +1,9 @@ +#!/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. + +import shutil +import sys + +shutil.copyfile(sys.argv[1], sys.argv[2]) diff --git a/tools/gyp/test/actions/multiple/src/filter.py b/tools/gyp/test/actions/multiple/src/filter.py new file mode 100644 index 00000000000000..f61a5fa59a9f1f --- /dev/null +++ b/tools/gyp/test/actions/multiple/src/filter.py @@ -0,0 +1,12 @@ +#!/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. + + +import sys + +data = open(sys.argv[3], 'r').read() +fh = open(sys.argv[4], 'w') +fh.write(data.replace(sys.argv[1], sys.argv[2])) +fh.close() diff --git a/tools/gyp/test/actions/multiple/src/foo.c b/tools/gyp/test/actions/multiple/src/foo.c new file mode 100644 index 00000000000000..23c4ef7f26fc47 --- /dev/null +++ b/tools/gyp/test/actions/multiple/src/foo.c @@ -0,0 +1,11 @@ +/* + * 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. + */ + +#include + +void foo(void) { + printf("foo\n"); +} diff --git a/tools/gyp/test/actions/multiple/src/input.txt b/tools/gyp/test/actions/multiple/src/input.txt new file mode 100644 index 00000000000000..c7c7da3c64e86c --- /dev/null +++ b/tools/gyp/test/actions/multiple/src/input.txt @@ -0,0 +1 @@ +hello there diff --git a/tools/gyp/test/actions/multiple/src/main.c b/tools/gyp/test/actions/multiple/src/main.c new file mode 100644 index 00000000000000..0a420b9034369f --- /dev/null +++ b/tools/gyp/test/actions/multiple/src/main.c @@ -0,0 +1,22 @@ +/* + * 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. + */ + +#include + +void bar(void); +void car(void); +void dar(void); +void ear(void); + +int main() { + printf("{\n"); + bar(); + car(); + dar(); + ear(); + printf("}\n"); + return 0; +} diff --git a/tools/gyp/test/actions/none/gyptest-none.py b/tools/gyp/test/actions/none/gyptest-none.py new file mode 100644 index 00000000000000..933cfad30c6619 --- /dev/null +++ b/tools/gyp/test/actions/none/gyptest-none.py @@ -0,0 +1,24 @@ +#!/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 actions can be in 'none' type targets with source files. +""" + +import TestGyp + +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') + +file_content = 'foo.cc\n' + +test.built_file_must_match('fake.out', file_content, chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/actions/none/src/fake_cross.py b/tools/gyp/test/actions/none/src/fake_cross.py new file mode 100644 index 00000000000000..a03ea87fc9c351 --- /dev/null +++ b/tools/gyp/test/actions/none/src/fake_cross.py @@ -0,0 +1,12 @@ +#!/usr/bin/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. + + +import sys + +fh = open(sys.argv[-1], 'w') +for filename in sys.argv[1:-1]: + fh.write(open(filename).read()) +fh.close() diff --git a/tools/gyp/test/actions/none/src/foo.cc b/tools/gyp/test/actions/none/src/foo.cc new file mode 100644 index 00000000000000..c6c61745badb78 --- /dev/null +++ b/tools/gyp/test/actions/none/src/foo.cc @@ -0,0 +1 @@ +foo.cc diff --git a/tools/gyp/test/actions/none/src/none_with_source_files.gyp b/tools/gyp/test/actions/none/src/none_with_source_files.gyp new file mode 100644 index 00000000000000..e2aaebc10a6d5e --- /dev/null +++ b/tools/gyp/test/actions/none/src/none_with_source_files.gyp @@ -0,0 +1,35 @@ +# 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. + +# Test that 'none' type targets can have .cc files in them. + +{ + 'targets': [ + { + 'target_name': 'none_with_sources', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'foo.cc', + ], + 'actions': [ + { + 'action_name': 'fake_cross', + 'inputs': [ + 'fake_cross.py', + '<@(_sources)', + ], + 'outputs': [ + '<(PRODUCT_DIR)/fake.out', + ], + 'action': [ + 'python', '<@(_inputs)', '<@(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + } + ], + }, + ], +} diff --git a/tools/gyp/test/actions/subdir/gyptest-action.py b/tools/gyp/test/actions/subdir/gyptest-action.py new file mode 100644 index 00000000000000..09cfef1893d56f --- /dev/null +++ b/tools/gyp/test/actions/subdir/gyptest-action.py @@ -0,0 +1,26 @@ +#!/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. + +""" +Test actions that output to PRODUCT_DIR. +""" + +import TestGyp + +# TODO fix this for xcode: http://code.google.com/p/gyp/issues/detail?id=88 +test = TestGyp.TestGyp(formats=['!xcode']) + +test.run_gyp('none.gyp', chdir='src') + +test.build('none.gyp', test.ALL, chdir='src') + +file_content = 'Hello from make-file.py\n' +subdir_file_content = 'Hello from make-subdir-file.py\n' + +test.built_file_must_match('file.out', file_content, chdir='src') +test.built_file_must_match('subdir_file.out', subdir_file_content, chdir='src') + +test.pass_test() diff --git a/tools/gyp/test/actions/subdir/src/make-file.py b/tools/gyp/test/actions/subdir/src/make-file.py new file mode 100644 index 00000000000000..6055ab9bb3c069 --- /dev/null +++ b/tools/gyp/test/actions/subdir/src/make-file.py @@ -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 = 'Hello from make-file.py\n' + +open(sys.argv[1], 'w').write(contents) diff --git a/tools/gyp/test/actions/subdir/src/none.gyp b/tools/gyp/test/actions/subdir/src/none.gyp new file mode 100644 index 00000000000000..23f8d25a53e44a --- /dev/null +++ b/tools/gyp/test/actions/subdir/src/none.gyp @@ -0,0 +1,31 @@ +# 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': 'file', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'actions': [ + { + 'action_name': 'make-file', + 'inputs': [ + 'make-file.py', + ], + 'outputs': [ + '<(PRODUCT_DIR)/file.out', + ], + 'action': [ + 'python', '<(_inputs)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + } + ], + 'dependencies': [ + 'subdir/subdir.gyp:subdir_file', + ], + }, + ], +} diff --git a/tools/gyp/test/actions/subdir/src/subdir/make-subdir-file.py b/tools/gyp/test/actions/subdir/src/subdir/make-subdir-file.py new file mode 100644 index 00000000000000..02c090a021e347 --- /dev/null +++ b/tools/gyp/test/actions/subdir/src/subdir/make-subdir-file.py @@ -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 = 'Hello from make-subdir-file.py\n' + +open(sys.argv[1], 'w').write(contents) diff --git a/tools/gyp/test/actions/subdir/src/subdir/subdir.gyp b/tools/gyp/test/actions/subdir/src/subdir/subdir.gyp new file mode 100644 index 00000000000000..0315d4eb83fefc --- /dev/null +++ b/tools/gyp/test/actions/subdir/src/subdir/subdir.gyp @@ -0,0 +1,28 @@ +# 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': 'subdir_file', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'actions': [ + { + 'action_name': 'make-subdir-file', + 'inputs': [ + 'make-subdir-file.py', + ], + 'outputs': [ + '<(PRODUCT_DIR)/subdir_file.out', + ], + 'action': [ + 'python', '<(_inputs)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + } + ], + }, + ], +} diff --git a/tools/gyp/test/additional-targets/gyptest-additional.py b/tools/gyp/test/additional-targets/gyptest-additional.py new file mode 100644 index 00000000000000..466283e55cb893 --- /dev/null +++ b/tools/gyp/test/additional-targets/gyptest-additional.py @@ -0,0 +1,63 @@ +#!/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 simple actions when using an explicit build target of 'all'. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('all.gyp', + '-G', 'xcode_ninja_target_pattern=^all_targets$', + chdir='src') + +test.relocate('src', 'relocate/src') + +# Build all. +test.build('all.gyp', chdir='relocate/src') + +if test.format=='xcode': + chdir = 'relocate/src/dir1' +else: + chdir = 'relocate/src' + +# Output is as expected. +file_content = 'Hello from emit.py\n' +test.built_file_must_match('out2.txt', file_content, chdir=chdir) + +test.built_file_must_not_exist('out.txt', chdir='relocate/src') +test.built_file_must_not_exist('foolib1', + 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', 'cmake'): + chdir='relocate/src' +else: + chdir='relocate/src/dir1' + +# Build the action explicitly. +test.build('actions.gyp', 'action1_target', chdir=chdir) + +# Check that things got run. +file_content = 'Hello from emit.py\n' +test.built_file_must_exist('out.txt', chdir=chdir) + +# Build the shared library explicitly. +test.build('actions.gyp', 'foolib1', chdir=chdir) + +test.built_file_must_exist('foolib1', + type=test.SHARED_LIB, + chdir=chdir, + subdir='dir1') + +test.pass_test() diff --git a/tools/gyp/test/additional-targets/src/all.gyp b/tools/gyp/test/additional-targets/src/all.gyp new file mode 100644 index 00000000000000..21c83080aaffef --- /dev/null +++ b/tools/gyp/test/additional-targets/src/all.gyp @@ -0,0 +1,13 @@ +# 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': 'all_targets', + 'type': 'none', + 'dependencies': ['dir1/actions.gyp:*'], + }, + ], +} diff --git a/tools/gyp/test/additional-targets/src/dir1/actions.gyp b/tools/gyp/test/additional-targets/src/dir1/actions.gyp new file mode 100644 index 00000000000000..5089c809131cb9 --- /dev/null +++ b/tools/gyp/test/additional-targets/src/dir1/actions.gyp @@ -0,0 +1,56 @@ +# 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': 'action1_target', + 'type': 'none', + 'suppress_wildcard': 1, + 'actions': [ + { + 'action_name': 'action1', + 'inputs': [ + 'emit.py', + ], + 'outputs': [ + '<(PRODUCT_DIR)/out.txt', + ], + 'action': ['python', 'emit.py', '<(PRODUCT_DIR)/out.txt'], + 'msvs_cygwin_shell': 0, + }, + ], + }, + { + 'target_name': 'action2_target', + 'type': 'none', + 'actions': [ + { + 'action_name': 'action2', + 'inputs': [ + 'emit.py', + ], + 'outputs': [ + '<(PRODUCT_DIR)/out2.txt', + ], + 'action': ['python', 'emit.py', '<(PRODUCT_DIR)/out2.txt'], + 'msvs_cygwin_shell': 0, + }, + ], + }, + { + 'target_name': 'foolib1', + 'type': 'shared_library', + 'suppress_wildcard': 1, + 'sources': ['lib1.c'], + }, + ], + 'conditions': [ + ['OS=="linux"', { + 'target_defaults': { + 'cflags': ['-fPIC'], + }, + }], + ], +} diff --git a/tools/gyp/test/additional-targets/src/dir1/emit.py b/tools/gyp/test/additional-targets/src/dir1/emit.py new file mode 100644 index 00000000000000..96db7a57df9ac3 --- /dev/null +++ b/tools/gyp/test/additional-targets/src/dir1/emit.py @@ -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 + +f = open(sys.argv[1], 'w') +f.write('Hello from emit.py\n') +f.close() diff --git a/tools/gyp/test/additional-targets/src/dir1/lib1.c b/tools/gyp/test/additional-targets/src/dir1/lib1.c new file mode 100644 index 00000000000000..df4cb10f796e29 --- /dev/null +++ b/tools/gyp/test/additional-targets/src/dir1/lib1.c @@ -0,0 +1,6 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int func1(void) { + return 42; +} diff --git a/tools/gyp/test/analyzer/common.gypi b/tools/gyp/test/analyzer/common.gypi new file mode 100644 index 00000000000000..7c664e40dabf4d --- /dev/null +++ b/tools/gyp/test/analyzer/common.gypi @@ -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 --git a/tools/gyp/test/analyzer/gyptest-analyzer.py b/tools/gyp/test/analyzer/gyptest-analyzer.py new file mode 100644 index 00000000000000..649b979af7fa1f --- /dev/null +++ b/tools/gyp/test/analyzer/gyptest-analyzer.py @@ -0,0 +1,402 @@ +#!/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 +""" + +from __future__ import print_function + +import json +import TestGyp + +found = 'Found dependency' +found_all = 'Found dependency (all)' +not_found = 'No dependencies' + + +def _CreateConfigFile(files, additional_compile_targets, test_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, + 'test_targets': test_targets, + 'additional_compile_targets': additional_compile_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(matched=False, compile_targets=set(), test_targets=set()): + """Verifies output contains |compile_targets|.""" + result = _ReadOutputFileContents() + if 'error' in result: + print('unexpected error', result.get('error')) + test.fail_test() + + if 'invalid_targets' in result: + print('unexpected invalid_targets', result.get('invalid_targets')) + test.fail_test() + + actual_compile_targets = set(result['compile_targets']) + if actual_compile_targets != compile_targets: + print('actual compile_targets:', actual_compile_targets, '\nexpected compile_targets:', compile_targets) + test.fail_test() + + actual_test_targets = set(result['test_targets']) + if actual_test_targets != test_targets: + print('actual test_targets:', actual_test_targets, '\nexpected test_targets:', test_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(compile_targets, test_targets=set()): + result = _ReadOutputFileContents() + if 'error' in result: + print('unexpected error', result.get('error')) + test.fail_test() + + if 'invalid_targets' in result: + 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_compile_targets = set(result['compile_targets']) + if actual_compile_targets != compile_targets: + print('actual compile_targets:', actual_compile_targets, '\nexpected compile_targets:', compile_targets) + test.fail_test() + + actual_test_targets = set(result['test_targets']) + if actual_test_targets != test_targets: + print('actual test_targets:', actual_test_targets, '\nexpected test_targets:', test_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'], ['all']) +test.run_gyp('static_library_test.gyp', *CommonArgs()) +EnsureContains(matched=True, compile_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'], ['all']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe'}) + +# Conditional source that is excluded. +_CreateConfigFile(['conditional_source.c'], ['all']) +run_analyzer() +EnsureContains(matched=False) + +# Conditional source that is included by way of argument. +_CreateConfigFile(['conditional_source.c'], ['all']) +run_analyzer('-Dtest_variable=1') +EnsureContains(matched=True, compile_targets={'exe'}) + +# Two unknown files. +_CreateConfigFile(['unknown1.c', 'unoknow2.cc'], ['all']) +run_analyzer() +EnsureContains() + +# Two unknown files. +_CreateConfigFile(['unknown1.c', 'subdir/subdir_sourcex.c'], ['all']) +run_analyzer() +EnsureContains() + +# Included dependency +_CreateConfigFile(['unknown1.c', 'subdir/subdir_source.c'], ['all']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe', 'exe3'}) + +# Included inputs to actions. +_CreateConfigFile(['action_input.c'], ['all']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe'}) + +# Don't consider outputs. +_CreateConfigFile(['action_output.c'], ['all']) +run_analyzer() +EnsureContains(matched=False) + +# Rule inputs. +_CreateConfigFile(['rule_input.c'], ['all']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe'}) + +# Ignore path specified with PRODUCT_DIR. +_CreateConfigFile(['product_dir_input.c'], ['all']) +run_analyzer() +EnsureContains(matched=False) + +# Path specified via a variable. +_CreateConfigFile(['subdir/subdir_source2.c'], ['all']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe'}) + +# Verifies paths with // are fixed up correctly. +_CreateConfigFile(['parent_source.c'], ['all']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe', 'exe3'}) + +# Verifies relative paths are resolved correctly. +_CreateConfigFile(['subdir/subdir_source.h'], ['all']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe'}) + +# Verifies relative paths in inputs are resolved correctly. +_CreateConfigFile(['rel_path1.h'], ['all']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe'}) + +# Various permutations when passing in targets. +_CreateConfigFile(['exe2.c', 'subdir/subdir2b_source.c'], ['all'], ['exe', 'exe3']) +run_analyzer() +EnsureContains(matched=True, test_targets={'exe3'}, compile_targets={'exe2', 'exe3'}) + +_CreateConfigFile(['exe2.c', 'subdir/subdir2b_source.c'], ['all'], ['exe']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe2', 'exe3'}) + +# Verifies duplicates are ignored. +_CreateConfigFile(['exe2.c', 'subdir/subdir2b_source.c'], ['all'], ['exe', 'exe']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe2', 'exe3'}) + +_CreateConfigFile(['exe2.c'], ['all'], ['exe']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe2'}) + +_CreateConfigFile(['exe2.c'], ['all']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe2'}) + +_CreateConfigFile(['subdir/subdir2b_source.c', 'exe2.c'], ['all']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe2', 'exe3'}) + +_CreateConfigFile(['subdir/subdir2b_source.c'], ['all'], ['exe3']) +run_analyzer() +EnsureContains(matched=True, test_targets={'exe3'}, compile_targets={'exe3'}) + +_CreateConfigFile(['exe2.c'], ['all']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe2'}) + +_CreateConfigFile(['foo.c'], ['all']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe'}) + +# Assertions when modifying build (gyp/gypi) files, especially when said files +# are included. +_CreateConfigFile(['subdir2/d.cc'], ['all'], ['exe', 'exe2', 'foo', 'exe3']) +run_analyzer2() +EnsureContains(matched=True, test_targets={'exe', 'foo'}, compile_targets={'exe', 'foo'}) + +_CreateConfigFile(['subdir2/subdir.includes.gypi'], ['all'], ['exe', 'exe2', 'foo', 'exe3']) +run_analyzer2() +EnsureContains(matched=True, test_targets={'exe', 'foo'}, compile_targets={'exe', 'foo'}) + +_CreateConfigFile(['subdir2/subdir.gyp'], ['all'], ['exe', 'exe2', 'foo', 'exe3']) +run_analyzer2() +EnsureContains(matched=True, test_targets={'exe', 'foo'}, compile_targets={'exe', 'foo'}) + +_CreateConfigFile(['test2.includes.gypi'], ['all'], ['exe', 'exe2', 'foo', 'exe3']) +run_analyzer2() +EnsureContains(matched=True, test_targets={'exe', 'exe2', 'exe3'}, compile_targets={'exe', 'exe2', 'exe3'}) + +# Verify modifying a file included makes all targets dirty. +_CreateConfigFile(['common.gypi'], ['all'], ['exe', 'exe2', 'foo', 'exe3']) +run_analyzer2('-Icommon.gypi') +EnsureMatchedAll({'all', 'exe', 'exe2', 'foo', 'exe3'}, {'exe', 'exe2', 'foo', 'exe3'}) + +# Assertions from test3.gyp. +_CreateConfigFile(['d.c', 'f.c'], ['all'], ['a']) +run_analyzer3() +EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a', 'b'}) + +_CreateConfigFile(['f.c'], ['all'], ['a']) +run_analyzer3() +EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a', 'b'}) + +_CreateConfigFile(['f.c'], ['all']) +run_analyzer3() +EnsureContains(matched=True, compile_targets={'a', 'b'}) + +_CreateConfigFile(['c.c', 'e.c'], ['all']) +run_analyzer3() +EnsureContains(matched=True, compile_targets={'a', 'b', 'c', 'e'}) + +_CreateConfigFile(['d.c'], ['all'], ['a']) +run_analyzer3() +EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a', 'b'}) + +_CreateConfigFile(['a.c'], ['all'], ['a', 'b']) +run_analyzer3() +EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a'}) + +_CreateConfigFile(['a.c'], ['all'], ['a', 'b']) +run_analyzer3() +EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a'}) + +_CreateConfigFile(['d.c'], ['all'], ['a', 'b']) +run_analyzer3() +EnsureContains(matched=True, test_targets={'a', 'b'}, compile_targets={'a', 'b'}) + +_CreateConfigFile(['f.c'], ['all'], ['a']) +run_analyzer3() +EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a', 'b'}) + +_CreateConfigFile(['a.c'], ['all'], ['a']) +run_analyzer3() +EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a'}) + +_CreateConfigFile(['a.c'], ['all']) +run_analyzer3() +EnsureContains(matched=True, compile_targets={'a'}) + +_CreateConfigFile(['d.c'], ['all']) +run_analyzer3() +EnsureContains(matched=True, compile_targets={'a', 'b'}) + +# Assertions around test4.gyp. +_CreateConfigFile(['f.c'], ['all']) +run_analyzer4() +EnsureContains(matched=True, compile_targets={'e', 'f'}) + +_CreateConfigFile(['d.c'], ['all']) +run_analyzer4() +EnsureContains(matched=True, compile_targets={'a', 'b', 'c', 'd'}) + +_CreateConfigFile(['i.c'], ['all']) +run_analyzer4() +EnsureContains(matched=True, compile_targets={'h', 'i'}) + +# Assertions where 'all' is not supplied in compile_targets. + +_CreateConfigFile(['exe2.c'], [], ['exe2']) +run_analyzer() +EnsureContains(matched=True, test_targets={'exe2'}, compile_targets={'exe2'}) + +_CreateConfigFile(['exe20.c'], [], ['exe2']) +run_analyzer() +EnsureContains(matched=False) + +_CreateConfigFile(['exe2.c', 'exe3.c'], [], ['exe2', 'exe3']) +run_analyzer() +EnsureContains(matched=True, test_targets={'exe2', 'exe3'}, compile_targets={'exe2', 'exe3'}) + +_CreateConfigFile(['exe2.c', 'exe3.c'], ['exe3'], ['exe2']) +run_analyzer() +EnsureContains(matched=True, test_targets={'exe2'}, compile_targets={'exe2', 'exe3'}) + +_CreateConfigFile(['exe3.c'], ['exe2'], ['exe2']) +run_analyzer() +EnsureContains(matched=False) + +# Assertions with 'all' listed as a test_target. +_CreateConfigFile(['exe3.c'], [], ['all']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe3', 'all'}, test_targets={'all'}) + +_CreateConfigFile(['exe2.c'], [], ['all', 'exe2']) +run_analyzer() +EnsureContains(matched=True, compile_targets={'exe2', 'all'}, test_targets={'all', 'exe2'}) + +test.pass_test() diff --git a/tools/gyp/test/analyzer/static_library_test.gyp b/tools/gyp/test/analyzer/static_library_test.gyp new file mode 100644 index 00000000000000..2c8e4bd826bb5e --- /dev/null +++ b/tools/gyp/test/analyzer/static_library_test.gyp @@ -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 --git a/tools/gyp/test/analyzer/subdir/subdir.gyp b/tools/gyp/test/analyzer/subdir/subdir.gyp new file mode 100644 index 00000000000000..bfa2df48e15b07 --- /dev/null +++ b/tools/gyp/test/analyzer/subdir/subdir.gyp @@ -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 --git a/tools/gyp/test/analyzer/subdir/subdir2/subdir2.gyp b/tools/gyp/test/analyzer/subdir/subdir2/subdir2.gyp new file mode 100644 index 00000000000000..e5aaa92b18c6b4 --- /dev/null +++ b/tools/gyp/test/analyzer/subdir/subdir2/subdir2.gyp @@ -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 --git a/tools/gyp/test/analyzer/subdir2/subdir.gyp b/tools/gyp/test/analyzer/subdir2/subdir.gyp new file mode 100644 index 00000000000000..d6c709c9ef4408 --- /dev/null +++ b/tools/gyp/test/analyzer/subdir2/subdir.gyp @@ -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 --git a/tools/gyp/test/analyzer/subdir2/subdir.includes.gypi b/tools/gyp/test/analyzer/subdir2/subdir.includes.gypi new file mode 100644 index 00000000000000..324e92bcd43c02 --- /dev/null +++ b/tools/gyp/test/analyzer/subdir2/subdir.includes.gypi @@ -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 --git a/tools/gyp/test/analyzer/test.gyp b/tools/gyp/test/analyzer/test.gyp new file mode 100644 index 00000000000000..c25ca73bff80dd --- /dev/null +++ b/tools/gyp/test/analyzer/test.gyp @@ -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 +# #allx (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': 'allx', + 'type': 'none', + 'dependencies': [ + 'exe', + 'exe3', + ], + }, + ], +} diff --git a/tools/gyp/test/analyzer/test2.gyp b/tools/gyp/test/analyzer/test2.gyp new file mode 100644 index 00000000000000..782b6e6428a7bf --- /dev/null +++ b/tools/gyp/test/analyzer/test2.gyp @@ -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 --git a/tools/gyp/test/analyzer/test2.includes.gypi b/tools/gyp/test/analyzer/test2.includes.gypi new file mode 100644 index 00000000000000..3e21de23cbe64d --- /dev/null +++ b/tools/gyp/test/analyzer/test2.includes.gypi @@ -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 --git a/tools/gyp/test/analyzer/test2.includes.includes.gypi b/tools/gyp/test/analyzer/test2.includes.includes.gypi new file mode 100644 index 00000000000000..de3a025dbb607d --- /dev/null +++ b/tools/gyp/test/analyzer/test2.includes.includes.gypi @@ -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 --git a/tools/gyp/test/analyzer/test2.toplevel_includes.gypi b/tools/gyp/test/analyzer/test2.toplevel_includes.gypi new file mode 100644 index 00000000000000..54fa453b085691 --- /dev/null +++ b/tools/gyp/test/analyzer/test2.toplevel_includes.gypi @@ -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 --git a/tools/gyp/test/analyzer/test3.gyp b/tools/gyp/test/analyzer/test3.gyp new file mode 100644 index 00000000000000..e52f6bc7d395cb --- /dev/null +++ b/tools/gyp/test/analyzer/test3.gyp @@ -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': 'allx', + '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 --git a/tools/gyp/test/analyzer/test4.gyp b/tools/gyp/test/analyzer/test4.gyp new file mode 100644 index 00000000000000..91cea56c1fe35f --- /dev/null +++ b/tools/gyp/test/analyzer/test4.gyp @@ -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 --git a/tools/gyp/test/analyzer/test5.gyp b/tools/gyp/test/analyzer/test5.gyp new file mode 100644 index 00000000000000..f3ea5b00612d08 --- /dev/null +++ b/tools/gyp/test/analyzer/test5.gyp @@ -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 --git a/tools/gyp/test/arflags/gyptest-arflags.py b/tools/gyp/test/arflags/gyptest-arflags.py new file mode 100644 index 00000000000000..870a2d894695aa --- /dev/null +++ b/tools/gyp/test/arflags/gyptest-arflags.py @@ -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 building a target with invalid arflags fails. +""" + +from __future__ import print_function + +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 --git a/tools/gyp/test/arflags/lib.cc b/tools/gyp/test/arflags/lib.cc new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/arflags/test.gyp b/tools/gyp/test/arflags/test.gyp new file mode 100644 index 00000000000000..f7430fae2d1359 --- /dev/null +++ b/tools/gyp/test/arflags/test.gyp @@ -0,0 +1,10 @@ +{ + 'targets': [ + { + 'target_name': 'lib', + 'type': 'static_library', + 'sources': ['lib.cc'], + 'arflags': ['--nonexistent'], + }, + ], +} diff --git a/tools/gyp/test/assembly/gyptest-assembly.py b/tools/gyp/test/assembly/gyptest-assembly.py new file mode 100644 index 00000000000000..8a84310544afc9 --- /dev/null +++ b/tools/gyp/test/assembly/gyptest-assembly.py @@ -0,0 +1,31 @@ +#!/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. + +""" +A basic test of compiling assembler files. +""" + +import sys +import TestGyp + +if sys.platform != 'win32': + # TODO(bradnelson): get this working for windows. + test = TestGyp.TestGyp(formats=['!msvs']) + + test.run_gyp('assembly.gyp', chdir='src') + + test.relocate('src', 'relocate/src') + + test.build('assembly.gyp', test.ALL, chdir='relocate/src') + + expect = """\ +Hello from program.c +Got 42. +""" + test.run_built_executable('program', chdir='relocate/src', stdout=expect) + + + test.pass_test() diff --git a/tools/gyp/test/assembly/gyptest-override.py b/tools/gyp/test/assembly/gyptest-override.py new file mode 100644 index 00000000000000..e84a23e855ac21 --- /dev/null +++ b/tools/gyp/test/assembly/gyptest-override.py @@ -0,0 +1,24 @@ +#!/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. + +""" +Make sure that manual rules on Windows override the built in ones. +""" + +import sys +import TestGyp + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + CHDIR = 'src' + test.run_gyp('override.gyp', chdir=CHDIR) + test.build('override.gyp', test.ALL, chdir=CHDIR) + expect = """\ +Hello from program.c +Got 42. +""" + test.run_built_executable('program', chdir=CHDIR, stdout=expect) + test.pass_test() diff --git a/tools/gyp/test/assembly/src/as.bat b/tools/gyp/test/assembly/src/as.bat new file mode 100644 index 00000000000000..b796db97ca56e7 --- /dev/null +++ b/tools/gyp/test/assembly/src/as.bat @@ -0,0 +1,4 @@ +@echo off +:: Mock windows assembler. +cl /MD /c %1 /Fo"%2" + diff --git a/tools/gyp/test/assembly/src/assembly.gyp b/tools/gyp/test/assembly/src/assembly.gyp new file mode 100644 index 00000000000000..565cb0fa0e3888 --- /dev/null +++ b/tools/gyp/test/assembly/src/assembly.gyp @@ -0,0 +1,62 @@ +# 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. + +{ + 'target_defaults': { + 'conditions': [ + ['OS=="win"', { + 'defines': ['PLATFORM_WIN'], + }], + ['OS=="mac" or OS=="ios"', { + 'defines': ['PLATFORM_MAC'], + }], + ['OS=="linux"', { + 'defines': ['PLATFORM_LINUX'], + }], + ['OS=="android"', { + 'defines': ['PLATFORM_ANDROID'], + }], + ], + }, + 'targets': [ + { + 'target_name': 'program', + 'type': 'executable', + 'dependencies': ['lib1'], + 'sources': [ + 'program.c', + ], + }, + { + 'target_name': 'lib1', + 'type': 'static_library', + 'sources': [ + 'lib1.S', + ], + }, + ], + 'conditions': [ + ['OS=="win"', { + 'target_defaults': { + 'rules': [ + { + 'rule_name': 'assembler', + 'msvs_cygwin_shell': 0, + 'extension': 'S', + 'inputs': [ + 'as.bat', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).obj', + ], + 'action': + ['as.bat', 'lib1.c', '<(_outputs)'], + 'message': 'Building assembly file <(RULE_INPUT_PATH)', + 'process_outputs_as_sources': 1, + }, + ], + }, + },], + ], +} diff --git a/tools/gyp/test/assembly/src/lib1.S b/tools/gyp/test/assembly/src/lib1.S new file mode 100644 index 00000000000000..7de9f19cf97383 --- /dev/null +++ b/tools/gyp/test/assembly/src/lib1.S @@ -0,0 +1,15 @@ +#if PLATFORM_WINDOWS || PLATFORM_MAC +# define IDENTIFIER(n) _##n +#else /* Linux */ +# define IDENTIFIER(n) n +#endif + +.globl IDENTIFIER(lib1_function) +IDENTIFIER(lib1_function): +#if !defined(PLATFORM_ANDROID) + movl $42, %eax + ret +#else /* Android (assuming ARM) */ + mov r0, #42 + bx lr +#endif diff --git a/tools/gyp/test/assembly/src/lib1.c b/tools/gyp/test/assembly/src/lib1.c new file mode 100644 index 00000000000000..be21ecd5f6a765 --- /dev/null +++ b/tools/gyp/test/assembly/src/lib1.c @@ -0,0 +1,3 @@ +int lib1_function(void) { + return 42; +} diff --git a/tools/gyp/test/assembly/src/override.gyp b/tools/gyp/test/assembly/src/override.gyp new file mode 100644 index 00000000000000..39a4072effc5cf --- /dev/null +++ b/tools/gyp/test/assembly/src/override.gyp @@ -0,0 +1,34 @@ +# 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': 'program', + 'type': 'executable', + 'sources': [ + 'program.c', + 'override_asm.asm', + ], + 'rules': [ + { + # Test that if there's a specific .asm rule, it overrides the + # built in one on Windows. + 'rule_name': 'assembler', + 'msvs_cygwin_shell': 0, + 'extension': 'asm', + 'inputs': [ + 'as.bat', + ], + 'outputs': [ + 'output.obj', + ], + 'action': ['as.bat', 'lib1.c', '<(_outputs)'], + 'message': 'Building assembly file <(RULE_INPUT_PATH)', + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/assembly/src/override_asm.asm b/tools/gyp/test/assembly/src/override_asm.asm new file mode 100644 index 00000000000000..be93b23baac3f5 --- /dev/null +++ b/tools/gyp/test/assembly/src/override_asm.asm @@ -0,0 +1,8 @@ +; 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. + +; This is a placeholder. It should not be referenced if overrides work +; correctly. + +Bad stuff that shouldn't assemble. diff --git a/tools/gyp/test/assembly/src/program.c b/tools/gyp/test/assembly/src/program.c new file mode 100644 index 00000000000000..eee862712e1916 --- /dev/null +++ b/tools/gyp/test/assembly/src/program.c @@ -0,0 +1,12 @@ +#include + +extern int lib1_function(void); + +int main(void) +{ + fprintf(stdout, "Hello from program.c\n"); + fflush(stdout); + fprintf(stdout, "Got %d.\n", lib1_function()); + fflush(stdout); + return 0; +} diff --git a/tools/gyp/test/build-option/gyptest-build.py b/tools/gyp/test/build-option/gyptest-build.py new file mode 100644 index 00000000000000..2782faa1b86408 --- /dev/null +++ b/tools/gyp/test/build-option/gyptest-build.py @@ -0,0 +1,24 @@ +#!/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 simplest-possible build of a "Hello, world!" program +using the default build target. +""" + +import TestGyp + +# The xcode-ninja generator doesn't support --build +# https://code.google.com/p/gyp/issues/detail?id=453 +test = TestGyp.TestGyp(workdir='workarea_default', formats=['!xcode-ninja']) + +test.run_gyp('hello.gyp', '--build=Default') + +test.run_built_executable('hello', stdout="Hello, world!\n") + +test.up_to_date('hello.gyp', test.DEFAULT) + +test.pass_test() diff --git a/tools/gyp/test/build-option/hello.c b/tools/gyp/test/build-option/hello.c new file mode 100644 index 00000000000000..f6ad129fd7a3db --- /dev/null +++ b/tools/gyp/test/build-option/hello.c @@ -0,0 +1,13 @@ +/* + * 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(void) +{ + printf("Hello, world!\n"); + return 0; +} diff --git a/tools/gyp/test/build-option/hello.gyp b/tools/gyp/test/build-option/hello.gyp new file mode 100644 index 00000000000000..1974d51ccd1934 --- /dev/null +++ b/tools/gyp/test/build-option/hello.gyp @@ -0,0 +1,15 @@ +# 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': 'hello', + 'type': 'executable', + 'sources': [ + 'hello.c', + ], + }, + ], +} diff --git a/tools/gyp/test/builddir/gyptest-all.py b/tools/gyp/test/builddir/gyptest-all.py new file mode 100644 index 00000000000000..85a08752cc64de --- /dev/null +++ b/tools/gyp/test/builddir/gyptest-all.py @@ -0,0 +1,85 @@ +#!/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 the settings that cause a set of programs to be created in +a specific build directory, and that no intermediate built files +get created outside of that build directory hierarchy even when +referred to with deeply-nested ../../.. paths. +""" + +import TestGyp + +# TODO(mmoss): Make only supports (theoretically) a single, global build +# directory (through GYP_GENERATOR_FLAGS 'output_dir'), rather than +# gyp-file-specific settings (e.g. the stuff in builddir.gypi) that the other +# generators support, so this doesn't work yet for make. +# TODO(mmoss) Make also has the issue that the top-level Makefile is written to +# the "--depth" location, which is one level above 'src', but then this test +# moves 'src' somewhere else, leaving the Makefile behind, so make can't find +# 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. +# 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': + if test.uses_msbuild: + test.must_contain('src/prog1.vcxproj', + '..\\builddir\\Default\\') + else: + test.must_contain('src/prog1.vcproj', + 'OutputDirectory="..\\builddir\\Default\\"') + +test.relocate('src', 'relocate/src') + +test.subdir('relocate/builddir') + +# Make sure that all the built ../../etc. files only get put under builddir, +# by making all of relocate read-only and then making only builddir writable. +test.writable('relocate', False) +test.writable('relocate/builddir', True) + +# Suppress the test infrastructure's setting SYMROOT on the command line. +test.build('prog1.gyp', test.ALL, SYMROOT=None, chdir='relocate/src') + +expect1 = """\ +Hello from prog1.c +Hello from func1.c +""" + +expect2 = """\ +Hello from subdir2/prog2.c +Hello from func2.c +""" + +expect3 = """\ +Hello from subdir2/subdir3/prog3.c +Hello from func3.c +""" + +expect4 = """\ +Hello from subdir2/subdir3/subdir4/prog4.c +Hello from func4.c +""" + +expect5 = """\ +Hello from subdir2/subdir3/subdir4/subdir5/prog5.c +Hello from func5.c +""" + +def run_builddir(prog, expect): + dir = 'relocate/builddir/Default/' + test.run_built_executable(test.workpath(dir + prog), stdout=expect) + +run_builddir('prog1', expect1) +run_builddir('prog2', expect2) +run_builddir('prog3', expect3) +run_builddir('prog4', expect4) +run_builddir('prog5', expect5) + +test.pass_test() diff --git a/tools/gyp/test/builddir/gyptest-default.py b/tools/gyp/test/builddir/gyptest-default.py new file mode 100644 index 00000000000000..a193d9e5fc85eb --- /dev/null +++ b/tools/gyp/test/builddir/gyptest-default.py @@ -0,0 +1,85 @@ +#!/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 the settings that cause a set of programs to be created in +a specific build directory, and that no intermediate built files +get created outside of that build directory hierarchy even when +referred to with deeply-nested ../../.. paths. +""" + +import TestGyp + +# TODO(mmoss): Make only supports (theoretically) a single, global build +# directory (through GYP_GENERATOR_FLAGS 'output_dir'), rather than +# gyp-file-specific settings (e.g. the stuff in builddir.gypi) that the other +# generators support, so this doesn't work yet for make. +# TODO(mmoss) Make also has the issue that the top-level Makefile is written to +# the "--depth" location, which is one level above 'src', but then this test +# moves 'src' somewhere else, leaving the Makefile behind, so make can't find +# 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. +# 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': + if test.uses_msbuild: + test.must_contain('src/prog1.vcxproj', + '..\\builddir\\Default\\') + else: + test.must_contain('src/prog1.vcproj', + 'OutputDirectory="..\\builddir\\Default\\"') + +test.relocate('src', 'relocate/src') + +test.subdir('relocate/builddir') + +# Make sure that all the built ../../etc. files only get put under builddir, +# by making all of relocate read-only and then making only builddir writable. +test.writable('relocate', False) +test.writable('relocate/builddir', True) + +# Suppress the test infrastructure's setting SYMROOT on the command line. +test.build('prog1.gyp', SYMROOT=None, chdir='relocate/src') + +expect1 = """\ +Hello from prog1.c +Hello from func1.c +""" + +expect2 = """\ +Hello from subdir2/prog2.c +Hello from func2.c +""" + +expect3 = """\ +Hello from subdir2/subdir3/prog3.c +Hello from func3.c +""" + +expect4 = """\ +Hello from subdir2/subdir3/subdir4/prog4.c +Hello from func4.c +""" + +expect5 = """\ +Hello from subdir2/subdir3/subdir4/subdir5/prog5.c +Hello from func5.c +""" + +def run_builddir(prog, expect): + dir = 'relocate/builddir/Default/' + test.run_built_executable(test.workpath(dir + prog), stdout=expect) + +run_builddir('prog1', expect1) +run_builddir('prog2', expect2) +run_builddir('prog3', expect3) +run_builddir('prog4', expect4) +run_builddir('prog5', expect5) + +test.pass_test() diff --git a/tools/gyp/test/builddir/src/builddir.gypi b/tools/gyp/test/builddir/src/builddir.gypi new file mode 100644 index 00000000000000..ce175db8f84dcb --- /dev/null +++ b/tools/gyp/test/builddir/src/builddir.gypi @@ -0,0 +1,18 @@ +# 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. + +{ + 'target_defaults': { + 'configurations': { + 'Default': { + 'msvs_configuration_attributes': { + 'OutputDirectory': '<(DEPTH)\\builddir/Default', + }, + }, + }, + }, + 'xcode_settings': { + 'SYMROOT': '<(DEPTH)/builddir', + }, +} diff --git a/tools/gyp/test/builddir/src/func1.c b/tools/gyp/test/builddir/src/func1.c new file mode 100644 index 00000000000000..b8e6a06951c987 --- /dev/null +++ b/tools/gyp/test/builddir/src/func1.c @@ -0,0 +1,6 @@ +#include + +void func1(void) +{ + printf("Hello from func1.c\n"); +} diff --git a/tools/gyp/test/builddir/src/func2.c b/tools/gyp/test/builddir/src/func2.c new file mode 100644 index 00000000000000..14aabac475ad2f --- /dev/null +++ b/tools/gyp/test/builddir/src/func2.c @@ -0,0 +1,6 @@ +#include + +void func2(void) +{ + printf("Hello from func2.c\n"); +} diff --git a/tools/gyp/test/builddir/src/func3.c b/tools/gyp/test/builddir/src/func3.c new file mode 100644 index 00000000000000..3b4edeae6ddbfc --- /dev/null +++ b/tools/gyp/test/builddir/src/func3.c @@ -0,0 +1,6 @@ +#include + +void func3(void) +{ + printf("Hello from func3.c\n"); +} diff --git a/tools/gyp/test/builddir/src/func4.c b/tools/gyp/test/builddir/src/func4.c new file mode 100644 index 00000000000000..732891b79a999c --- /dev/null +++ b/tools/gyp/test/builddir/src/func4.c @@ -0,0 +1,6 @@ +#include + +void func4(void) +{ + printf("Hello from func4.c\n"); +} diff --git a/tools/gyp/test/builddir/src/func5.c b/tools/gyp/test/builddir/src/func5.c new file mode 100644 index 00000000000000..18fdfabbbed858 --- /dev/null +++ b/tools/gyp/test/builddir/src/func5.c @@ -0,0 +1,6 @@ +#include + +void func5(void) +{ + printf("Hello from func5.c\n"); +} diff --git a/tools/gyp/test/builddir/src/prog1.c b/tools/gyp/test/builddir/src/prog1.c new file mode 100644 index 00000000000000..a32aaf04f9dcc7 --- /dev/null +++ b/tools/gyp/test/builddir/src/prog1.c @@ -0,0 +1,10 @@ +#include + +extern void func1(void); + +int main(void) +{ + printf("Hello from prog1.c\n"); + func1(); + return 0; +} diff --git a/tools/gyp/test/builddir/src/prog1.gyp b/tools/gyp/test/builddir/src/prog1.gyp new file mode 100644 index 00000000000000..5b96f035ec707c --- /dev/null +++ b/tools/gyp/test/builddir/src/prog1.gyp @@ -0,0 +1,30 @@ +# 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. + +{ + 'includes': [ + 'builddir.gypi', + ], + 'targets': [ + { + 'target_name': 'pull_in_all', + 'type': 'none', + 'dependencies': [ + 'prog1', + 'subdir2/prog2.gyp:prog2', + 'subdir2/subdir3/prog3.gyp:prog3', + 'subdir2/subdir3/subdir4/prog4.gyp:prog4', + 'subdir2/subdir3/subdir4/subdir5/prog5.gyp:prog5', + ], + }, + { + 'target_name': 'prog1', + 'type': 'executable', + 'sources': [ + 'prog1.c', + 'func1.c', + ], + }, + ], +} diff --git a/tools/gyp/test/builddir/src/subdir2/prog2.c b/tools/gyp/test/builddir/src/subdir2/prog2.c new file mode 100644 index 00000000000000..9d682cd783c8ad --- /dev/null +++ b/tools/gyp/test/builddir/src/subdir2/prog2.c @@ -0,0 +1,10 @@ +#include + +extern void func2(void); + +int main(void) +{ + printf("Hello from subdir2/prog2.c\n"); + func2(); + return 0; +} diff --git a/tools/gyp/test/builddir/src/subdir2/prog2.gyp b/tools/gyp/test/builddir/src/subdir2/prog2.gyp new file mode 100644 index 00000000000000..96299b646d2116 --- /dev/null +++ b/tools/gyp/test/builddir/src/subdir2/prog2.gyp @@ -0,0 +1,19 @@ +# 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. + +{ + 'includes': [ + '../builddir.gypi', + ], + 'targets': [ + { + 'target_name': 'prog2', + 'type': 'executable', + 'sources': [ + 'prog2.c', + '../func2.c', + ], + }, + ], +} diff --git a/tools/gyp/test/builddir/src/subdir2/subdir3/prog3.c b/tools/gyp/test/builddir/src/subdir2/subdir3/prog3.c new file mode 100644 index 00000000000000..da74965985e56c --- /dev/null +++ b/tools/gyp/test/builddir/src/subdir2/subdir3/prog3.c @@ -0,0 +1,10 @@ +#include + +extern void func3(void); + +int main(void) +{ + printf("Hello from subdir2/subdir3/prog3.c\n"); + func3(); + return 0; +} diff --git a/tools/gyp/test/builddir/src/subdir2/subdir3/prog3.gyp b/tools/gyp/test/builddir/src/subdir2/subdir3/prog3.gyp new file mode 100644 index 00000000000000..d7df43c7bde92f --- /dev/null +++ b/tools/gyp/test/builddir/src/subdir2/subdir3/prog3.gyp @@ -0,0 +1,19 @@ +# 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. + +{ + 'includes': [ + '../../builddir.gypi', + ], + 'targets': [ + { + 'target_name': 'prog3', + 'type': 'executable', + 'sources': [ + 'prog3.c', + '../../func3.c', + ], + }, + ], +} diff --git a/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.c b/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.c new file mode 100644 index 00000000000000..5787d5fa4368bc --- /dev/null +++ b/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.c @@ -0,0 +1,10 @@ +#include + +extern void func4(void); + +int main(void) +{ + printf("Hello from subdir2/subdir3/subdir4/prog4.c\n"); + func4(); + return 0; +} diff --git a/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.gyp b/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.gyp new file mode 100644 index 00000000000000..862a8a18cd70f8 --- /dev/null +++ b/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.gyp @@ -0,0 +1,19 @@ +# 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. + +{ + 'includes': [ + '../../../builddir.gypi', + ], + 'targets': [ + { + 'target_name': 'prog4', + 'type': 'executable', + 'sources': [ + 'prog4.c', + '../../../func4.c', + ], + }, + ], +} diff --git a/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.c b/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.c new file mode 100644 index 00000000000000..c6e2ab521f4333 --- /dev/null +++ b/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.c @@ -0,0 +1,10 @@ +#include + +extern void func5(void); + +int main(void) +{ + printf("Hello from subdir2/subdir3/subdir4/subdir5/prog5.c\n"); + func5(); + return 0; +} diff --git a/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.gyp b/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.gyp new file mode 100644 index 00000000000000..fe1c9cbf50f49a --- /dev/null +++ b/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.gyp @@ -0,0 +1,19 @@ +# 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. + +{ + 'includes': [ + '../../../../builddir.gypi', + ], + 'targets': [ + { + 'target_name': 'prog5', + 'type': 'executable', + 'sources': [ + 'prog5.c', + '../../../../func5.c', + ], + }, + ], +} diff --git a/tools/gyp/test/cflags/cflags.c b/tools/gyp/test/cflags/cflags.c new file mode 100644 index 00000000000000..0a02ba90745e80 --- /dev/null +++ b/tools/gyp/test/cflags/cflags.c @@ -0,0 +1,15 @@ +/* Copyright (c) 2010 Google 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) +{ +#ifdef FOO + printf("FOO defined\n"); +#else + printf("FOO not defined\n"); +#endif + return 0; +} diff --git a/tools/gyp/test/cflags/cflags.gyp b/tools/gyp/test/cflags/cflags.gyp new file mode 100644 index 00000000000000..2840dc63185d04 --- /dev/null +++ b/tools/gyp/test/cflags/cflags.gyp @@ -0,0 +1,23 @@ +# Copyright (c) 2010 Google 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': 'cflags', + 'type': 'executable', + 'sources': [ + 'cflags.c', + ], + }, + { + 'target_name': 'cflags_host', + 'toolsets': ['host'], + 'type': 'executable', + 'sources': [ + 'cflags.c', + ], + }, + ], +} diff --git a/tools/gyp/test/cflags/gyptest-cflags.py b/tools/gyp/test/cflags/gyptest-cflags.py new file mode 100644 index 00000000000000..f4efccba9bb50b --- /dev/null +++ b/tools/gyp/test/cflags/gyptest-cflags.py @@ -0,0 +1,75 @@ +#!/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 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 TestGyp + +# CPPFLAGS works in ninja but not make; CFLAGS works in both +FORMATS = ('make', 'ninja') + +test = TestGyp.TestGyp(formats=FORMATS) + +# 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') + +expect = """FOO not defined\n""" +test.run_built_executable('cflags', stdout=expect) +test.run_built_executable('cflags_host', stdout=expect) + +test.sleep() + +with TestGyp.LocalEnv({'CFLAGS': '-DFOO=1', + 'GYP_CROSSCOMPILE': '1'}): + test.run_gyp('cflags.gyp') + test.build('cflags.gyp') + +expect = """FOO defined\n""" +test.run_built_executable('cflags', stdout=expect) + +# Environment variable CFLAGS shouldn't influence the flags for the host. +expect = """FOO not defined\n""" +test.run_built_executable('cflags_host', stdout=expect) + +test.sleep() + +with TestGyp.LocalEnv({'CFLAGS_host': '-DFOO=1', + 'GYP_CROSSCOMPILE': '1'}): + test.run_gyp('cflags.gyp') + test.build('cflags.gyp') + +# Environment variable CFLAGS_host should influence the flags for the host. +expect = """FOO defined\n""" +test.run_built_executable('cflags_host', stdout=expect) + +test.sleep() + +with TestGyp.LocalEnv({'CFLAGS': ''}): + test.run_gyp('cflags.gyp') + test.build('cflags.gyp') + +expect = """FOO not defined\n""" +test.run_built_executable('cflags', stdout=expect) + +test.sleep() + +with TestGyp.LocalEnv({'CFLAGS': '-DFOO=1'}): + test.run_gyp('cflags.gyp') + test.build('cflags.gyp') + +expect = """FOO defined\n""" +test.run_built_executable('cflags', stdout=expect) + +test.pass_test() diff --git a/tools/gyp/test/compilable/gyptest-headers.py b/tools/gyp/test/compilable/gyptest-headers.py new file mode 100644 index 00000000000000..91760216fbb55f --- /dev/null +++ b/tools/gyp/test/compilable/gyptest-headers.py @@ -0,0 +1,29 @@ +#!/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 that .hpp files are ignored when included in the source list on all +platforms. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('headers.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('headers.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from program.c +Hello from lib1.c +""" +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + + +test.pass_test() diff --git a/tools/gyp/test/compilable/src/headers.gyp b/tools/gyp/test/compilable/src/headers.gyp new file mode 100644 index 00000000000000..b6c2a8857be940 --- /dev/null +++ b/tools/gyp/test/compilable/src/headers.gyp @@ -0,0 +1,26 @@ +# 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': 'program', + 'type': 'executable', + 'dependencies': [ + 'lib1' + ], + 'sources': [ + 'program.cpp', + ], + }, + { + 'target_name': 'lib1', + 'type': 'static_library', + 'sources': [ + 'lib1.hpp', + 'lib1.cpp', + ], + }, + ], +} diff --git a/tools/gyp/test/compilable/src/lib1.cpp b/tools/gyp/test/compilable/src/lib1.cpp new file mode 100644 index 00000000000000..51bc31a40b86fa --- /dev/null +++ b/tools/gyp/test/compilable/src/lib1.cpp @@ -0,0 +1,7 @@ +#include +#include "lib1.hpp" + +void lib1_function(void) { + fprintf(stdout, "Hello from lib1.c\n"); + fflush(stdout); +} diff --git a/tools/gyp/test/compilable/src/lib1.hpp b/tools/gyp/test/compilable/src/lib1.hpp new file mode 100644 index 00000000000000..72e63e8acdbd70 --- /dev/null +++ b/tools/gyp/test/compilable/src/lib1.hpp @@ -0,0 +1,6 @@ +#ifndef _lib1_hpp +#define _lib1_hpp + +extern void lib1_function(void); + +#endif diff --git a/tools/gyp/test/compilable/src/program.cpp b/tools/gyp/test/compilable/src/program.cpp new file mode 100644 index 00000000000000..8af2c9b6ffcb22 --- /dev/null +++ b/tools/gyp/test/compilable/src/program.cpp @@ -0,0 +1,9 @@ +#include +#include "lib1.hpp" + +int main(void) { + fprintf(stdout, "Hello from program.c\n"); + fflush(stdout); + lib1_function(); + return 0; +} diff --git a/tools/gyp/test/compiler-override/compiler-exe.gyp b/tools/gyp/test/compiler-override/compiler-exe.gyp new file mode 100644 index 00000000000000..c2f3002f20724d --- /dev/null +++ b/tools/gyp/test/compiler-override/compiler-exe.gyp @@ -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 --git a/tools/gyp/test/compiler-override/compiler-global-settings.gyp.in b/tools/gyp/test/compiler-override/compiler-global-settings.gyp.in new file mode 100644 index 00000000000000..ca13a53e8d88bb --- /dev/null +++ b/tools/gyp/test/compiler-override/compiler-global-settings.gyp.in @@ -0,0 +1,34 @@ +# 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. + +{ + # PYTHON and PWD are replaced by the test code before this + # gyp file runs + 'make_global_settings': [ + ['CC', r'$PYTHON $PWD/my_cc.py FOO'], + ['CXX', r'$PYTHON $PWD/my_cxx.py FOO'], + ['CC.host', r'$PYTHON $PWD/my_cc.py BAR'], + ['CXX.host', r'$PYTHON $PWD/my_cxx.py BAR'], + + ['LD', r'$PYTHON $PWD/my_ld.py FOO_LINK'], + ['LD.host', r'$PYTHON $PWD/my_ld.py BAR_LINK'], + ['LINK', r'$PYTHON $PWD/my_ld.py FOO_LINK'], + ['LINK.host', r'$PYTHON $PWD/my_ld.py BAR_LINK'], + ], + + # The above global settings should mean that + # that these targets are built using the fake + # toolchain above. + 'targets': [ + { + 'toolset': '$TOOLSET', + 'target_name': 'hello', + 'type': 'executable', + 'sources': [ + 'test.c', + 'cxxtest.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/compiler-override/compiler-host.gyp b/tools/gyp/test/compiler-override/compiler-host.gyp new file mode 100644 index 00000000000000..ab3d247e0bfe19 --- /dev/null +++ b/tools/gyp/test/compiler-override/compiler-host.gyp @@ -0,0 +1,17 @@ +# 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': [ + { + 'toolset': 'host', + 'target_name': 'hello', + 'type': 'executable', + 'sources': [ + 'test.c', + 'cxxtest.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/compiler-override/compiler-shared-lib.gyp b/tools/gyp/test/compiler-override/compiler-shared-lib.gyp new file mode 100644 index 00000000000000..d3e4316135db06 --- /dev/null +++ b/tools/gyp/test/compiler-override/compiler-shared-lib.gyp @@ -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 --git a/tools/gyp/test/compiler-override/cxxtest.cc b/tools/gyp/test/compiler-override/cxxtest.cc new file mode 100644 index 00000000000000..517a3536196283 --- /dev/null +++ b/tools/gyp/test/compiler-override/cxxtest.cc @@ -0,0 +1,7 @@ +// 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. + +// Deliberate C syntax error as this file should never be passed to +// the actual compiler +#error Should not be passed to a real compiler diff --git a/tools/gyp/test/compiler-override/gyptest-compiler-env-toolchain.py b/tools/gyp/test/compiler-override/gyptest-compiler-env-toolchain.py new file mode 100644 index 00000000000000..2361d0c7c2a4c4 --- /dev/null +++ b/tools/gyp/test/compiler-override/gyptest-compiler-env-toolchain.py @@ -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 --git a/tools/gyp/test/compiler-override/gyptest-compiler-env.py b/tools/gyp/test/compiler-override/gyptest-compiler-env.py new file mode 100644 index 00000000000000..bb38b6e55bea9b --- /dev/null +++ b/tools/gyp/test/compiler-override/gyptest-compiler-env.py @@ -0,0 +1,110 @@ +#!/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/LD +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']: + 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', 'make']) + +def TestTargetOveride(): + expected = ['my_cc.py', 'my_cxx.py', 'FOO' ] + + # 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 + oldenv = os.environ.copy() + try: + os.environ['CC'] = 'python %s/my_cc.py FOO' % here + os.environ['CXX'] = 'python %s/my_cxx.py FOO' % here + os.environ['LINK'] = 'python %s/my_ld.py FOO_LINK' % here + + CheckCompiler(test, 'compiler-exe.gyp', expected, True) + finally: + os.environ.clear() + os.environ.update(oldenv) + + # 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-exe.gyp', expected, False) + + +def TestTargetOverideCompilerOnly(): + # Same test again but with that CC, CXX and not LD + oldenv = os.environ.copy() + try: + os.environ['CC'] = 'python %s/my_cc.py FOO' % here + os.environ['CXX'] = 'python %s/my_cxx.py FOO' % here + + CheckCompiler(test, 'compiler-exe.gyp', + ['my_cc.py', 'my_cxx.py', 'FOO'], + True) + finally: + os.environ.clear() + os.environ.update(oldenv) + + # 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-exe.gyp', + ['my_cc.py', 'my_cxx.py', 'FOO'], + False) + + +def TestHostOveride(): + expected = ['my_cc.py', 'my_cxx.py', 'HOST' ] + if test.format != 'ninja': # ninja just uses $CC / $CXX as linker. + expected.append('HOST_LINK') + + # Check that CC_host sets host compilee + oldenv = os.environ.copy() + try: + os.environ['CC_host'] = 'python %s/my_cc.py HOST' % here + os.environ['CXX_host'] = 'python %s/my_cxx.py HOST' % here + os.environ['LINK_host'] = 'python %s/my_ld.py HOST_LINK' % here + CheckCompiler(test, 'compiler-host.gyp', expected, True) + finally: + os.environ.clear() + os.environ.update(oldenv) + + # 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-host.gyp', expected, False) + + +TestTargetOveride() +TestTargetOverideCompilerOnly() + +test.pass_test() diff --git a/tools/gyp/test/compiler-override/gyptest-compiler-global-settings.py b/tools/gyp/test/compiler-override/gyptest-compiler-global-settings.py new file mode 100644 index 00000000000000..9f062a4fef72e1 --- /dev/null +++ b/tools/gyp/test/compiler-override/gyptest-compiler-global-settings.py @@ -0,0 +1,82 @@ +#!/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 make_global_settings can be used to override the +compiler settings. +""" +from __future__ import print_function + +import TestGyp +import os +import copy +import sys +from string import Template + + +if sys.platform == 'win32': + # cross compiling not support by ninja on windows + # and make not supported on windows at all. + sys.exit(0) + +print("This test is currently disabled: https://crbug.com/483696.") +sys.exit(0) + +test = TestGyp.TestGyp(formats=['ninja', 'make']) + +gypfile = 'compiler-global-settings.gyp' + +replacements = { 'PYTHON': '/usr/bin/python', 'PWD': os.getcwd()} + +# Process the .in gyp file to produce the final gyp file +# since we need to include absolute paths in the make_global_settings +# section. +replacements['TOOLSET'] = 'target' +s = Template(open(gypfile + '.in').read()) +output = open(gypfile, 'w') +output.write(s.substitute(replacements)) +output.close() + +old_env = dict(os.environ) +os.environ['GYP_CROSSCOMPILE'] = '1' +test.run_gyp(gypfile) +os.environ.clear() +os.environ.update(old_env) + +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()) +output = open(gypfile, 'w') +output.write(s.substitute(replacements)) +output.close() + +old_env = dict(os.environ) +os.environ['GYP_CROSSCOMPILE'] = '1' +test.run_gyp(gypfile) +os.environ.clear() +os.environ.update(old_env) + +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 --git a/tools/gyp/test/compiler-override/my_cc.py b/tools/gyp/test/compiler-override/my_cc.py new file mode 100644 index 00000000000000..09e1d3c58d18ec --- /dev/null +++ b/tools/gyp/test/compiler-override/my_cc.py @@ -0,0 +1,7 @@ +#!/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. +from __future__ import print_function +import sys +print(sys.argv) diff --git a/tools/gyp/test/compiler-override/my_cxx.py b/tools/gyp/test/compiler-override/my_cxx.py new file mode 100644 index 00000000000000..09e1d3c58d18ec --- /dev/null +++ b/tools/gyp/test/compiler-override/my_cxx.py @@ -0,0 +1,7 @@ +#!/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. +from __future__ import print_function +import sys +print(sys.argv) diff --git a/tools/gyp/test/compiler-override/my_ld.py b/tools/gyp/test/compiler-override/my_ld.py new file mode 100644 index 00000000000000..09e1d3c58d18ec --- /dev/null +++ b/tools/gyp/test/compiler-override/my_ld.py @@ -0,0 +1,7 @@ +#!/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. +from __future__ import print_function +import sys +print(sys.argv) diff --git a/tools/gyp/test/compiler-override/my_nm.py b/tools/gyp/test/compiler-override/my_nm.py new file mode 100644 index 00000000000000..2c4e678110bb21 --- /dev/null +++ b/tools/gyp/test/compiler-override/my_nm.py @@ -0,0 +1,9 @@ +#!/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. +from __future__ import print_function +import sys +print(sys.argv) +with open('RAN_MY_NM', 'w') as f: + f.write('RAN_MY_NM') diff --git a/tools/gyp/test/compiler-override/my_readelf.py b/tools/gyp/test/compiler-override/my_readelf.py new file mode 100644 index 00000000000000..626665435e680e --- /dev/null +++ b/tools/gyp/test/compiler-override/my_readelf.py @@ -0,0 +1,9 @@ +#!/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. +from __future__ import print_function +import sys +print(sys.argv) +with open('RAN_MY_READELF', 'w') as f: + f.write('RAN_MY_READELF') diff --git a/tools/gyp/test/compiler-override/test.c b/tools/gyp/test/compiler-override/test.c new file mode 100644 index 00000000000000..517a3536196283 --- /dev/null +++ b/tools/gyp/test/compiler-override/test.c @@ -0,0 +1,7 @@ +// 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. + +// Deliberate C syntax error as this file should never be passed to +// the actual compiler +#error Should not be passed to a real compiler diff --git a/tools/gyp/test/conditions/elseif/elseif.gyp b/tools/gyp/test/conditions/elseif/elseif.gyp new file mode 100644 index 00000000000000..6367ff7d7afef5 --- /dev/null +++ b/tools/gyp/test/conditions/elseif/elseif.gyp @@ -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 --git a/tools/gyp/test/conditions/elseif/elseif_bad1.gyp b/tools/gyp/test/conditions/elseif/elseif_bad1.gyp new file mode 100644 index 00000000000000..35c8455ccae177 --- /dev/null +++ b/tools/gyp/test/conditions/elseif/elseif_bad1.gyp @@ -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 --git a/tools/gyp/test/conditions/elseif/elseif_bad2.gyp b/tools/gyp/test/conditions/elseif/elseif_bad2.gyp new file mode 100644 index 00000000000000..b529f292c06f98 --- /dev/null +++ b/tools/gyp/test/conditions/elseif/elseif_bad2.gyp @@ -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 --git a/tools/gyp/test/conditions/elseif/elseif_bad3.gyp b/tools/gyp/test/conditions/elseif/elseif_bad3.gyp new file mode 100644 index 00000000000000..126e18605373b7 --- /dev/null +++ b/tools/gyp/test/conditions/elseif/elseif_bad3.gyp @@ -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 --git a/tools/gyp/test/conditions/elseif/elseif_conditions.gypi b/tools/gyp/test/conditions/elseif/elseif_conditions.gypi new file mode 100644 index 00000000000000..4310ccc0312890 --- /dev/null +++ b/tools/gyp/test/conditions/elseif/elseif_conditions.gypi @@ -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 --git a/tools/gyp/test/conditions/elseif/gyptest_elseif.py b/tools/gyp/test/conditions/elseif/gyptest_elseif.py new file mode 100644 index 00000000000000..9d030cf3fe0a8a --- /dev/null +++ b/tools/gyp/test/conditions/elseif/gyptest_elseif.py @@ -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 --git a/tools/gyp/test/conditions/elseif/program.cc b/tools/gyp/test/conditions/elseif/program.cc new file mode 100644 index 00000000000000..147fe2f75e4694 --- /dev/null +++ b/tools/gyp/test/conditions/elseif/program.cc @@ -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 --git a/tools/gyp/test/configurations/basics/configurations.c b/tools/gyp/test/configurations/basics/configurations.c new file mode 100644 index 00000000000000..39e13c9c83fb0f --- /dev/null +++ b/tools/gyp/test/configurations/basics/configurations.c @@ -0,0 +1,15 @@ +#include + +int main(void) +{ +#ifdef FOO + printf("Foo configuration\n"); +#endif +#ifdef DEBUG + printf("Debug configuration\n"); +#endif +#ifdef RELEASE + printf("Release configuration\n"); +#endif + return 0; +} diff --git a/tools/gyp/test/configurations/basics/configurations.gyp b/tools/gyp/test/configurations/basics/configurations.gyp new file mode 100644 index 00000000000000..93f1d8d5c7fe09 --- /dev/null +++ b/tools/gyp/test/configurations/basics/configurations.gyp @@ -0,0 +1,32 @@ +# 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': 'configurations', + 'type': 'executable', + 'sources': [ + 'configurations.c', + ], + 'configurations': { + 'Debug': { + 'defines': [ + 'DEBUG', + ], + }, + 'Release': { + 'defines': [ + 'RELEASE', + ], + }, + 'Foo': { + 'defines': [ + 'FOO', + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/basics/gyptest-configurations.py b/tools/gyp/test/configurations/basics/gyptest-configurations.py new file mode 100644 index 00000000000000..27cd2e87d22437 --- /dev/null +++ b/tools/gyp/test/configurations/basics/gyptest-configurations.py @@ -0,0 +1,29 @@ +#!/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 build of an executable in three different configurations. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('configurations.gyp') + +test.set_configuration('Release') +test.build('configurations.gyp') +test.run_built_executable('configurations', stdout="Release configuration\n") + +test.set_configuration('Debug') +test.build('configurations.gyp') +test.run_built_executable('configurations', stdout="Debug configuration\n") + +test.set_configuration('Foo') +test.build('configurations.gyp') +test.run_built_executable('configurations', stdout="Foo configuration\n") + +test.pass_test() diff --git a/tools/gyp/test/configurations/inheritance/configurations.c b/tools/gyp/test/configurations/inheritance/configurations.c new file mode 100644 index 00000000000000..ebb9f8450e2722 --- /dev/null +++ b/tools/gyp/test/configurations/inheritance/configurations.c @@ -0,0 +1,21 @@ +#include + +int main(void) +{ +#ifdef BASE + printf("Base configuration\n"); +#endif +#ifdef COMMON + printf("Common configuration\n"); +#endif +#ifdef COMMON2 + printf("Common2 configuration\n"); +#endif +#ifdef DEBUG + printf("Debug configuration\n"); +#endif +#ifdef RELEASE + printf("Release configuration\n"); +#endif + return 0; +} diff --git a/tools/gyp/test/configurations/inheritance/configurations.gyp b/tools/gyp/test/configurations/inheritance/configurations.gyp new file mode 100644 index 00000000000000..9441376b4d1b2b --- /dev/null +++ b/tools/gyp/test/configurations/inheritance/configurations.gyp @@ -0,0 +1,40 @@ +# 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. + +{ + 'target_defaults': { + 'configurations': { + 'Base': { + 'abstract': 1, + 'defines': ['BASE'], + }, + 'Common': { + 'abstract': 1, + 'inherit_from': ['Base'], + 'defines': ['COMMON'], + }, + 'Common2': { + 'abstract': 1, + 'defines': ['COMMON2'], + }, + 'Debug': { + 'inherit_from': ['Common', 'Common2'], + 'defines': ['DEBUG'], + }, + 'Release': { + 'inherit_from': ['Common', 'Common2'], + 'defines': ['RELEASE'], + }, + }, + }, + 'targets': [ + { + 'target_name': 'configurations', + 'type': 'executable', + 'sources': [ + 'configurations.c', + ], + }, + ], +} diff --git a/tools/gyp/test/configurations/inheritance/duplicates.gyp b/tools/gyp/test/configurations/inheritance/duplicates.gyp new file mode 100644 index 00000000000000..6930ce3b39a12b --- /dev/null +++ b/tools/gyp/test/configurations/inheritance/duplicates.gyp @@ -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 --git a/tools/gyp/test/configurations/inheritance/duplicates.gypd.golden b/tools/gyp/test/configurations/inheritance/duplicates.gypd.golden new file mode 100644 index 00000000000000..719b70861e326f --- /dev/null +++ b/tools/gyp/test/configurations/inheritance/duplicates.gypd.golden @@ -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 --git a/tools/gyp/test/configurations/inheritance/gyptest-duplicates.py b/tools/gyp/test/configurations/inheritance/gyptest-duplicates.py new file mode 100644 index 00000000000000..f015638b6ddd7b --- /dev/null +++ b/tools/gyp/test/configurations/inheritance/gyptest-duplicates.py @@ -0,0 +1,36 @@ +#!/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. +""" + +from __future__ import print_function + +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 --git a/tools/gyp/test/configurations/inheritance/gyptest-inheritance.py b/tools/gyp/test/configurations/inheritance/gyptest-inheritance.py new file mode 100644 index 00000000000000..22c73a3754d982 --- /dev/null +++ b/tools/gyp/test/configurations/inheritance/gyptest-inheritance.py @@ -0,0 +1,33 @@ +#!/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 build of an executable in three different configurations. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('configurations.gyp') + +test.set_configuration('Release') +test.build('configurations.gyp') +test.run_built_executable('configurations', + stdout=('Base configuration\n' + 'Common configuration\n' + 'Common2 configuration\n' + 'Release configuration\n')) + +test.set_configuration('Debug') +test.build('configurations.gyp') +test.run_built_executable('configurations', + stdout=('Base configuration\n' + 'Common configuration\n' + 'Common2 configuration\n' + 'Debug configuration\n')) + +test.pass_test() diff --git a/tools/gyp/test/configurations/invalid/actions.gyp b/tools/gyp/test/configurations/invalid/actions.gyp new file mode 100644 index 00000000000000..a6e42089ebaf3c --- /dev/null +++ b/tools/gyp/test/configurations/invalid/actions.gyp @@ -0,0 +1,18 @@ +# Copyright (c) 2010 Google 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'actions': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/all_dependent_settings.gyp b/tools/gyp/test/configurations/invalid/all_dependent_settings.gyp new file mode 100644 index 00000000000000..b16a245df5468c --- /dev/null +++ b/tools/gyp/test/configurations/invalid/all_dependent_settings.gyp @@ -0,0 +1,18 @@ +# Copyright (c) 2010 Google 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'all_dependent_settings': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/configurations.gyp b/tools/gyp/test/configurations/invalid/configurations.gyp new file mode 100644 index 00000000000000..2cfc9600498ec8 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/configurations.gyp @@ -0,0 +1,18 @@ +# Copyright (c) 2010 Google 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'configurations': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/dependencies.gyp b/tools/gyp/test/configurations/invalid/dependencies.gyp new file mode 100644 index 00000000000000..74633f3f111337 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/dependencies.gyp @@ -0,0 +1,18 @@ +# Copyright (c) 2010 Google 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'dependencies': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/direct_dependent_settings.gyp b/tools/gyp/test/configurations/invalid/direct_dependent_settings.gyp new file mode 100644 index 00000000000000..8a0f2e95ea7138 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/direct_dependent_settings.gyp @@ -0,0 +1,18 @@ +# Copyright (c) 2010 Google 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'direct_dependent_settings': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/gyptest-configurations.py b/tools/gyp/test/configurations/invalid/gyptest-configurations.py new file mode 100644 index 00000000000000..bd844b95dd8a33 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/gyptest-configurations.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python + +# Copyright (c) 2010 Google 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 build of an executable in three different configurations. +""" + +import TestGyp + +# Keys that do not belong inside a configuration dictionary. +invalid_configuration_keys = [ + 'actions', + 'all_dependent_settings', + 'configurations', + 'dependencies', + 'direct_dependent_settings', + 'libraries', + 'link_settings', + 'sources', + 'standalone_static_library', + 'target_name', + 'type', +] + +test = TestGyp.TestGyp() + +for test_key in invalid_configuration_keys: + test.run_gyp('%s.gyp' % test_key, status=1, stderr=None) + expect = ['%s not allowed in the Debug configuration, found in target ' + '%s.gyp:configurations#target' % (test_key, test_key)] + test.must_contain_all_lines(test.stderr(), expect) + +test.pass_test() diff --git a/tools/gyp/test/configurations/invalid/libraries.gyp b/tools/gyp/test/configurations/invalid/libraries.gyp new file mode 100644 index 00000000000000..c4014ed4065dc0 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/libraries.gyp @@ -0,0 +1,18 @@ +# Copyright (c) 2010 Google 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'libraries': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/link_settings.gyp b/tools/gyp/test/configurations/invalid/link_settings.gyp new file mode 100644 index 00000000000000..2f0e1c46f5c98c --- /dev/null +++ b/tools/gyp/test/configurations/invalid/link_settings.gyp @@ -0,0 +1,18 @@ +# Copyright (c) 2010 Google 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'link_settings': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/sources.gyp b/tools/gyp/test/configurations/invalid/sources.gyp new file mode 100644 index 00000000000000..b38cca03818967 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/sources.gyp @@ -0,0 +1,18 @@ +# Copyright (c) 2010 Google 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'sources': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/standalone_static_library.gyp b/tools/gyp/test/configurations/invalid/standalone_static_library.gyp new file mode 100644 index 00000000000000..2edb9febd64ab5 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/standalone_static_library.gyp @@ -0,0 +1,17 @@ +# 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'standalone_static_library': 1, + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/target_name.gyp b/tools/gyp/test/configurations/invalid/target_name.gyp new file mode 100644 index 00000000000000..83baad95d60069 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/target_name.gyp @@ -0,0 +1,18 @@ +# Copyright (c) 2010 Google 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'target_name': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/type.gyp b/tools/gyp/test/configurations/invalid/type.gyp new file mode 100644 index 00000000000000..bc55898b89e063 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/type.gyp @@ -0,0 +1,18 @@ +# Copyright (c) 2010 Google 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'type': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/target_platform/configurations.gyp b/tools/gyp/test/configurations/target_platform/configurations.gyp new file mode 100644 index 00000000000000..d15429f4e5d7eb --- /dev/null +++ b/tools/gyp/test/configurations/target_platform/configurations.gyp @@ -0,0 +1,58 @@ +# 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. + +{ + 'target_defaults': { + 'configurations': { + 'Debug_Win32': { + 'msvs_configuration_platform': 'Win32', + }, + 'Debug_x64': { + 'msvs_configuration_platform': 'x64', + }, + }, + }, + 'targets': [ + { + 'target_name': 'left', + 'type': 'static_library', + 'sources': [ + 'left.c', + ], + 'configurations': { + 'Debug_Win32': { + 'msvs_target_platform': 'x64', + }, + }, + }, + { + 'target_name': 'right', + 'type': 'static_library', + 'sources': [ + 'right.c', + ], + }, + { + 'target_name': 'front_left', + 'type': 'executable', + 'dependencies': ['left'], + 'sources': [ + 'front.c', + ], + 'configurations': { + 'Debug_Win32': { + 'msvs_target_platform': 'x64', + }, + }, + }, + { + 'target_name': 'front_right', + 'type': 'executable', + 'dependencies': ['right'], + 'sources': [ + 'front.c', + ], + }, + ], +} diff --git a/tools/gyp/test/configurations/target_platform/front.c b/tools/gyp/test/configurations/target_platform/front.c new file mode 100644 index 00000000000000..7a91689ff5c130 --- /dev/null +++ b/tools/gyp/test/configurations/target_platform/front.c @@ -0,0 +1,8 @@ +#include + +const char *message(void); + +int main(void) { + printf("%s\n", message()); + return 0; +} diff --git a/tools/gyp/test/configurations/target_platform/gyptest-target_platform.py b/tools/gyp/test/configurations/target_platform/gyptest-target_platform.py new file mode 100644 index 00000000000000..3a7a845c30497a --- /dev/null +++ b/tools/gyp/test/configurations/target_platform/gyptest-target_platform.py @@ -0,0 +1,39 @@ +#!/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. + +""" +Tests the msvs specific msvs_target_platform option. +""" + +import TestGyp + + +def RunX64(exe, stdout): + try: + test.run_built_executable(exe, stdout=stdout) + except WindowsError as e: + # Assume the exe is 64-bit if it can't load on 32-bit systems. + # Both versions of the error are required because different versions + # of python seem to return different errors for invalid exe type. + if e.errno != 193 and '[Error 193]' not in str(e): + raise + + +test = TestGyp.TestGyp(formats=['msvs']) + +test.run_gyp('configurations.gyp') + +test.set_configuration('Debug|x64') +test.build('configurations.gyp', rebuild=True) +RunX64('front_left', stdout=('left\n')) +RunX64('front_right', stdout=('right\n')) + +test.set_configuration('Debug|Win32') +test.build('configurations.gyp', rebuild=True) +RunX64('front_left', stdout=('left\n')) +test.run_built_executable('front_right', stdout=('right\n')) + +test.pass_test() diff --git a/tools/gyp/test/configurations/target_platform/left.c b/tools/gyp/test/configurations/target_platform/left.c new file mode 100644 index 00000000000000..1ce2ea1227218f --- /dev/null +++ b/tools/gyp/test/configurations/target_platform/left.c @@ -0,0 +1,3 @@ +const char *message(void) { + return "left"; +} diff --git a/tools/gyp/test/configurations/target_platform/right.c b/tools/gyp/test/configurations/target_platform/right.c new file mode 100644 index 00000000000000..b1578492fe407d --- /dev/null +++ b/tools/gyp/test/configurations/target_platform/right.c @@ -0,0 +1,3 @@ +const char *message(void) { + return "right"; +} diff --git a/tools/gyp/test/configurations/x64/configurations.c b/tools/gyp/test/configurations/x64/configurations.c new file mode 100644 index 00000000000000..37018438fc7bfe --- /dev/null +++ b/tools/gyp/test/configurations/x64/configurations.c @@ -0,0 +1,12 @@ +#include + +int main(void) { + if (sizeof(void*) == 4) { + printf("Running Win32\n"); + } else if (sizeof(void*) == 8) { + printf("Running x64\n"); + } else { + printf("Unexpected platform\n"); + } + return 0; +} diff --git a/tools/gyp/test/configurations/x64/configurations.gyp b/tools/gyp/test/configurations/x64/configurations.gyp new file mode 100644 index 00000000000000..8b0139f1418904 --- /dev/null +++ b/tools/gyp/test/configurations/x64/configurations.gyp @@ -0,0 +1,38 @@ +# 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. + +{ + 'target_defaults': { + 'configurations': { + 'Debug': { + 'msvs_configuration_platform': 'Win32', + }, + 'Debug_x64': { + 'inherit_from': ['Debug'], + 'msvs_configuration_platform': 'x64', + }, + }, + }, + 'targets': [ + { + 'target_name': 'configurations', + 'type': 'executable', + 'sources': [ + 'configurations.c', + ], + }, + { + 'target_name': 'configurations64', + 'type': 'executable', + 'sources': [ + 'configurations.c', + ], + 'configurations': { + 'Debug': { + 'msvs_target_platform': 'x64', + }, + }, + }, + ], +} diff --git a/tools/gyp/test/configurations/x64/gyptest-x86.py b/tools/gyp/test/configurations/x64/gyptest-x86.py new file mode 100644 index 00000000000000..87e77e3c479037 --- /dev/null +++ b/tools/gyp/test/configurations/x64/gyptest-x86.py @@ -0,0 +1,29 @@ +#!/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 build of an executable in three different configurations. +""" + +import TestGyp + +import sys + +formats = ['msvs'] +if sys.platform == 'win32': + formats += ['ninja'] +test = TestGyp.TestGyp(formats=formats) + +test.run_gyp('configurations.gyp') +test.set_configuration('Debug|Win32') +test.build('configurations.gyp', test.ALL) + +for machine, suffix in [('14C machine (x86)', ''), ('8664 machine (x64)', '64')]: + output = test.run_dumpbin('/headers', test.built_file_path('configurations%s.exe' % suffix)) + if machine not in output: + test.fail_test() + +test.pass_test() diff --git a/tools/gyp/test/copies/gyptest-all.py b/tools/gyp/test/copies/gyptest-all.py new file mode 100644 index 00000000000000..aeccf3324c1c2e --- /dev/null +++ b/tools/gyp/test/copies/gyptest-all.py @@ -0,0 +1,42 @@ +#!/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 file copies using an explicit build target of 'all'. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('copies.gyp', + '-G', 'xcode_ninja_target_pattern=^(?!copies_null)', + chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('copies.gyp', test.ALL, chdir='relocate/src') + +test.must_match(['relocate', 'src', 'copies-out', 'file1'], 'file1 contents\n') + +test.built_file_must_match('copies-out/file2', + 'file2 contents\n', + chdir='relocate/src') + +test.built_file_must_match('copies-out/directory/file3', + 'file3 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out/directory/file4', + 'file4 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out/directory/subdir/file5', + 'file5 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out/subdir/file6', + 'file6 contents\n', + chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/copies/gyptest-attribs.py b/tools/gyp/test/copies/gyptest-attribs.py new file mode 100644 index 00000000000000..24c5cfbf6036b0 --- /dev/null +++ b/tools/gyp/test/copies/gyptest-attribs.py @@ -0,0 +1,39 @@ +#!/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') + 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 --git a/tools/gyp/test/copies/gyptest-default.py b/tools/gyp/test/copies/gyptest-default.py new file mode 100644 index 00000000000000..a916869f0dbd3c --- /dev/null +++ b/tools/gyp/test/copies/gyptest-default.py @@ -0,0 +1,42 @@ +#!/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 file copies using the build tool default. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('copies.gyp', + '-G', 'xcode_ninja_target_pattern=^(?!copies_null)', + chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('copies.gyp', chdir='relocate/src') + +test.must_match(['relocate', 'src', 'copies-out', 'file1'], 'file1 contents\n') + +test.built_file_must_match('copies-out/file2', + 'file2 contents\n', + chdir='relocate/src') + +test.built_file_must_match('copies-out/directory/file3', + 'file3 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out/directory/file4', + 'file4 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out/directory/subdir/file5', + 'file5 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out/subdir/file6', + 'file6 contents\n', + chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/copies/gyptest-samedir.py b/tools/gyp/test/copies/gyptest-samedir.py new file mode 100644 index 00000000000000..923ca615575821 --- /dev/null +++ b/tools/gyp/test/copies/gyptest-samedir.py @@ -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. + +""" +Verifies file copies where two copies sections in the same target have the +same destination directory. +""" + +import TestGyp + +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') + +test.built_file_must_match('copies-out-samedir/file1', + 'file1 contents\n', + chdir='relocate/src') + +test.built_file_must_match('copies-out-samedir/file2', + 'file2 contents\n', + chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/copies/gyptest-slash.py b/tools/gyp/test/copies/gyptest-slash.py new file mode 100644 index 00000000000000..f7a2e549ebe65f --- /dev/null +++ b/tools/gyp/test/copies/gyptest-slash.py @@ -0,0 +1,39 @@ +#!/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 file copies with a trailing slash in the destination directory. +""" + +import TestGyp + +test = TestGyp.TestGyp() +test.run_gyp('copies-slash.gyp', chdir='src') + +test.relocate('src', 'relocate/src') +test.build('copies-slash.gyp', chdir='relocate/src') + +test.built_file_must_match('copies-out-slash/directory/file3', + 'file3 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out-slash/directory/file4', + 'file4 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out-slash/directory/subdir/file5', + 'file5 contents\n', + chdir='relocate/src') + +test.built_file_must_match('copies-out-slash-2/directory/file3', + 'file3 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out-slash-2/directory/file4', + 'file4 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out-slash-2/directory/subdir/file5', + 'file5 contents\n', + chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/copies/gyptest-sourceless-shared-lib.py b/tools/gyp/test/copies/gyptest-sourceless-shared-lib.py new file mode 100644 index 00000000000000..6ec2e512ad22d6 --- /dev/null +++ b/tools/gyp/test/copies/gyptest-sourceless-shared-lib.py @@ -0,0 +1,20 @@ +#!/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 copies in sourceless shared_library targets are executed. +""" + +import TestGyp + +test = TestGyp.TestGyp() +test.run_gyp('copies-sourceless-shared-lib.gyp', chdir='src') +test.relocate('src', 'relocate/src') +test.build('copies-sourceless-shared-lib.gyp', chdir='relocate/src') +test.built_file_must_match('copies-out/file1', + 'file1 contents\n', + chdir='relocate/src') +test.pass_test() diff --git a/tools/gyp/test/copies/gyptest-updir.py b/tools/gyp/test/copies/gyptest-updir.py new file mode 100644 index 00000000000000..47a2ca2e1d5837 --- /dev/null +++ b/tools/gyp/test/copies/gyptest-updir.py @@ -0,0 +1,32 @@ +#!/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 file copies where the destination is one level above an expansion that +yields a make variable. +""" + +from __future__ import print_function + +import sys + +import TestGyp + +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') + +test.built_file_must_match('../copies-out-updir/file1', + 'file1 contents\n', + chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/copies/src/copies-attribs.gyp b/tools/gyp/test/copies/src/copies-attribs.gyp new file mode 100644 index 00000000000000..073e0d0cf677d4 --- /dev/null +++ b/tools/gyp/test/copies/src/copies-attribs.gyp @@ -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 --git a/tools/gyp/test/copies/src/copies-samedir.gyp b/tools/gyp/test/copies/src/copies-samedir.gyp new file mode 100644 index 00000000000000..2919ce503eda42 --- /dev/null +++ b/tools/gyp/test/copies/src/copies-samedir.gyp @@ -0,0 +1,37 @@ +# 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': 'copies_samedir', + 'type': 'none', + 'dependencies': [ + 'copies_samedir_dependency', + ], + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out-samedir', + 'files': [ + 'file1', + ], + }, + ], + }, + { + 'target_name': 'copies_samedir_dependency', + 'type': 'none', + 'direct_dependent_settings': { + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out-samedir', + 'files': [ + 'file2', + ], + }, + ], + }, + }, + ], +} diff --git a/tools/gyp/test/copies/src/copies-slash.gyp b/tools/gyp/test/copies/src/copies-slash.gyp new file mode 100644 index 00000000000000..9bf54bd1814942 --- /dev/null +++ b/tools/gyp/test/copies/src/copies-slash.gyp @@ -0,0 +1,36 @@ +# 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': [ + # A trailing slash on the destination directory should be ignored. + { + 'target_name': 'copies_recursive_trailing_slash', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out-slash/', + 'files': [ + 'directory/', + ], + }, + ], + }, + # Even if the source directory is below <(PRODUCT_DIR). + { + 'target_name': 'copies_recursive_trailing_slash_in_product_dir', + 'type': 'none', + 'dependencies': [ ':copies_recursive_trailing_slash' ], + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out-slash-2/', + 'files': [ + '<(PRODUCT_DIR)/copies-out-slash/directory/', + ], + }, + ], + }, + ], +} + diff --git a/tools/gyp/test/copies/src/copies-sourceless-shared-lib.gyp b/tools/gyp/test/copies/src/copies-sourceless-shared-lib.gyp new file mode 100644 index 00000000000000..7908f716a9071b --- /dev/null +++ b/tools/gyp/test/copies/src/copies-sourceless-shared-lib.gyp @@ -0,0 +1,27 @@ +# 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': 'mylib', + 'type': 'static_library', + 'sources': [ 'foo.c' ], + }, + { + 'target_name': 'mysolib', + 'type': 'shared_library', + 'dependencies': [ 'mylib' ], + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out', + 'files': [ 'file1' ], + }, + ], + # link.exe gets confused by sourceless shared libraries and needs this + # to become unconfused. + 'msvs_settings': { 'VCLinkerTool': { 'TargetMachine': '1', }, }, + }, + ], +} diff --git a/tools/gyp/test/copies/src/copies-updir.gyp b/tools/gyp/test/copies/src/copies-updir.gyp new file mode 100644 index 00000000000000..bd3bfdd1d2e3c3 --- /dev/null +++ b/tools/gyp/test/copies/src/copies-updir.gyp @@ -0,0 +1,21 @@ +# 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': 'copies_up', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/../copies-out-updir', + 'files': [ + 'file1', + ], + }, + ], + }, + ], +} + diff --git a/tools/gyp/test/copies/src/copies.gyp b/tools/gyp/test/copies/src/copies.gyp new file mode 100644 index 00000000000000..ce2e0cabca5431 --- /dev/null +++ b/tools/gyp/test/copies/src/copies.gyp @@ -0,0 +1,70 @@ +# 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': 'copies1', + 'type': 'none', + 'copies': [ + { + 'destination': 'copies-out', + 'files': [ + 'file1', + ], + }, + ], + }, + { + 'target_name': 'copies2', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out', + 'files': [ + 'file2', + ], + }, + ], + }, + # Copy a directory tree. + { + 'target_name': 'copies_recursive', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out', + 'files': [ + 'directory/', + ], + }, + ], + }, + # Copy a directory from deeper in the tree (this should not reproduce the + # entire directory path in the destination, only the final directory). + { + 'target_name': 'copies_recursive_depth', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out', + 'files': [ + 'parentdir/subdir/', + ], + }, + ], + }, + # Verify that a null 'files' list doesn't gag the generators. + { + 'target_name': 'copies_null', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-null', + 'files': [], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/copies/src/directory/file3 b/tools/gyp/test/copies/src/directory/file3 new file mode 100644 index 00000000000000..43f16f35220657 --- /dev/null +++ b/tools/gyp/test/copies/src/directory/file3 @@ -0,0 +1 @@ +file3 contents diff --git a/tools/gyp/test/copies/src/directory/file4 b/tools/gyp/test/copies/src/directory/file4 new file mode 100644 index 00000000000000..5f7270a0847cc6 --- /dev/null +++ b/tools/gyp/test/copies/src/directory/file4 @@ -0,0 +1 @@ +file4 contents diff --git a/tools/gyp/test/copies/src/directory/subdir/file5 b/tools/gyp/test/copies/src/directory/subdir/file5 new file mode 100644 index 00000000000000..41f47186bd2197 --- /dev/null +++ b/tools/gyp/test/copies/src/directory/subdir/file5 @@ -0,0 +1 @@ +file5 contents diff --git a/tools/gyp/test/copies/src/executable-file.sh b/tools/gyp/test/copies/src/executable-file.sh new file mode 100644 index 00000000000000..796953a1a2cf23 --- /dev/null +++ b/tools/gyp/test/copies/src/executable-file.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +echo echo echo echo cho ho o o diff --git a/tools/gyp/test/copies/src/file1 b/tools/gyp/test/copies/src/file1 new file mode 100644 index 00000000000000..84d55c5759cf6b --- /dev/null +++ b/tools/gyp/test/copies/src/file1 @@ -0,0 +1 @@ +file1 contents diff --git a/tools/gyp/test/copies/src/file2 b/tools/gyp/test/copies/src/file2 new file mode 100644 index 00000000000000..af1b8ae35db461 --- /dev/null +++ b/tools/gyp/test/copies/src/file2 @@ -0,0 +1 @@ +file2 contents diff --git a/tools/gyp/test/copies/src/foo.c b/tools/gyp/test/copies/src/foo.c new file mode 100644 index 00000000000000..99a4c103ba236c --- /dev/null +++ b/tools/gyp/test/copies/src/foo.c @@ -0,0 +1,13 @@ +// 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 f() { return 42; } + +#ifdef _MSC_VER +// link.exe gets confused by sourceless shared libraries and needs this +// to become unconfused. +int __stdcall _DllMainCRTStartup( + unsigned hInst, unsigned reason, void* reserved) { + return 1; +} +#endif diff --git a/tools/gyp/test/copies/src/parentdir/subdir/file6 b/tools/gyp/test/copies/src/parentdir/subdir/file6 new file mode 100644 index 00000000000000..f5d57573486772 --- /dev/null +++ b/tools/gyp/test/copies/src/parentdir/subdir/file6 @@ -0,0 +1 @@ +file6 contents diff --git a/tools/gyp/test/custom-generator/gyptest-custom-generator.py b/tools/gyp/test/custom-generator/gyptest-custom-generator.py new file mode 100644 index 00000000000000..85fd0724a13fc5 --- /dev/null +++ b/tools/gyp/test/custom-generator/gyptest-custom-generator.py @@ -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. + +"""Test that custom generators can be passed to --format +""" + +import TestGyp + +test = TestGyp.TestGypCustom(format='mygenerator.py') +test.run_gyp('test.gyp') + +# mygenerator.py should generate a file called MyBuildFile containing +# "Testing..." alongside the gyp file. +test.must_match('MyBuildFile', 'Testing...\n') + +test.pass_test() diff --git a/tools/gyp/test/custom-generator/mygenerator.py b/tools/gyp/test/custom-generator/mygenerator.py new file mode 100644 index 00000000000000..73529fdc6d6b30 --- /dev/null +++ b/tools/gyp/test/custom-generator/mygenerator.py @@ -0,0 +1,14 @@ +# 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. + +"""Custom gyp generator that doesn't do much.""" + +generator_default_variables = {} + + +# noinspection PyUnusedLocal +def GenerateOutput(target_list, target_dicts, data, params): + f = open("MyBuildFile", "w") + f.write("Testing...\n") + f.close() diff --git a/tools/gyp/test/custom-generator/test.gyp b/tools/gyp/test/custom-generator/test.gyp new file mode 100644 index 00000000000000..aa5f864a3b7bfa --- /dev/null +++ b/tools/gyp/test/custom-generator/test.gyp @@ -0,0 +1,15 @@ +# Copyright (c) 2010 Google 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', + 'sources': [ + 'main.c', + ], + }, + ], +} diff --git a/tools/gyp/test/cxxflags/cxxflags.cc b/tools/gyp/test/cxxflags/cxxflags.cc new file mode 100644 index 00000000000000..e70e39dfd35d02 --- /dev/null +++ b/tools/gyp/test/cxxflags/cxxflags.cc @@ -0,0 +1,15 @@ +/* Copyright (c) 2010 Google 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) +{ +#ifdef ABC + printf("With define\n"); +#else + printf("No define\n"); +#endif + return 0; +} diff --git a/tools/gyp/test/cxxflags/cxxflags.gyp b/tools/gyp/test/cxxflags/cxxflags.gyp new file mode 100644 index 00000000000000..a082d494924f94 --- /dev/null +++ b/tools/gyp/test/cxxflags/cxxflags.gyp @@ -0,0 +1,15 @@ +# Copyright (c) 2010 Google 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': 'cxxflags', + 'type': 'executable', + 'sources': [ + 'cxxflags.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/cxxflags/gyptest-cxxflags.py b/tools/gyp/test/cxxflags/gyptest-cxxflags.py new file mode 100644 index 00000000000000..117a1800de49d3 --- /dev/null +++ b/tools/gyp/test/cxxflags/gyptest-cxxflags.py @@ -0,0 +1,45 @@ +#!/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 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 TestGyp + +FORMATS = ('ninja',) + +test = TestGyp.TestGyp(formats=FORMATS) + +# 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') + +test.build('cxxflags.gyp') + +expect = """\ +No define +""" +test.run_built_executable('cxxflags', stdout=expect) + +test.sleep() + +with TestGyp.LocalEnv({'CXXFLAGS': '-DABC'}): + test.run_gyp('cxxflags.gyp') + +test.build('cxxflags.gyp') + +expect = """\ +With define +""" +test.run_built_executable('cxxflags', stdout=expect) + +test.pass_test() diff --git a/tools/gyp/test/defines-escaping/defines-escaping.c b/tools/gyp/test/defines-escaping/defines-escaping.c new file mode 100644 index 00000000000000..a0aa4c286d9fad --- /dev/null +++ b/tools/gyp/test/defines-escaping/defines-escaping.c @@ -0,0 +1,11 @@ +/* Copyright (c) 2010 Google 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(TEST_FORMAT, TEST_ARGS); + return 0; +} diff --git a/tools/gyp/test/defines-escaping/defines-escaping.gyp b/tools/gyp/test/defines-escaping/defines-escaping.gyp new file mode 100644 index 00000000000000..6f0f3fde41fdcd --- /dev/null +++ b/tools/gyp/test/defines-escaping/defines-escaping.gyp @@ -0,0 +1,19 @@ +# 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': 'defines_escaping', + 'type': 'executable', + 'sources': [ + 'defines-escaping.c', + ], + 'defines': [ + 'TEST_FORMAT="<(test_format)"', + 'TEST_ARGS=<(test_args)', + ], + }, + ], +} diff --git a/tools/gyp/test/defines-escaping/gyptest-defines-escaping.py b/tools/gyp/test/defines-escaping/gyptest-defines-escaping.py new file mode 100644 index 00000000000000..eb18a3d369f48d --- /dev/null +++ b/tools/gyp/test/defines-escaping/gyptest-defines-escaping.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python + +# Copyright (c) 2010 Google 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 build of an executable with C++ define specified by a gyp define using +various special characters such as quotes, commas, etc. +""" + +import os +import TestGyp + +test = TestGyp.TestGyp() + +# Tests string literals, percents, and backslash escapes. +try: + os.environ['GYP_DEFINES'] = ( + r"""test_format='\n%s\n' """ + r"""test_args='"Simple test of %s with a literal"'""") + test.run_gyp('defines-escaping.gyp') +finally: + del os.environ['GYP_DEFINES'] + +test.build('defines-escaping.gyp') + +expect = """ +Simple test of %s with a literal +""" +test.run_built_executable('defines_escaping', stdout=expect) + + +# Test multiple comma-and-space-separated string literals. +try: + os.environ['GYP_DEFINES'] = \ + r"""test_format='\n%s and %s\n' test_args='"foo", "bar"'""" + test.run_gyp('defines-escaping.gyp') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines-escaping.c') +test.build('defines-escaping.gyp') + +expect = """ +foo and bar +""" +test.run_built_executable('defines_escaping', stdout=expect) + + +# Test string literals containing quotes. +try: + os.environ['GYP_DEFINES'] = ( + r"""test_format='\n%s %s %s %s %s\n' """ + r"""test_args='"\"These,\"",""" + r""" "\"words,\"",""" + r""" "\"are,\"",""" + r""" "\"in,\"",""" + r""" "\"quotes.\""'""") + test.run_gyp('defines-escaping.gyp') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines-escaping.c') +test.build('defines-escaping.gyp') + +expect = """ +"These," "words," "are," "in," "quotes." +""" +test.run_built_executable('defines_escaping', stdout=expect) + + +# Test string literals containing single quotes. +try: + os.environ['GYP_DEFINES'] = ( + r"""test_format='\n%s %s %s %s %s\n' """ + r"""test_args="\"'These,'\",""" + r""" \"'words,'\",""" + r""" \"'are,'\",""" + r""" \"'in,'\",""" + r""" \"'quotes.'\"" """) + test.run_gyp('defines-escaping.gyp') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines-escaping.c') +test.build('defines-escaping.gyp') + +expect = """ +'These,' 'words,' 'are,' 'in,' 'quotes.' +""" +test.run_built_executable('defines_escaping', stdout=expect) + + +# Test string literals containing different numbers of backslashes before quotes +# (to exercise Windows' quoting behaviour). +try: + os.environ['GYP_DEFINES'] = ( + r"""test_format='\n%s\n%s\n%s\n' """ + r"""test_args='"\\\"1 visible slash\\\"",""" + r""" "\\\\\"2 visible slashes\\\\\"",""" + r""" "\\\\\\\"3 visible slashes\\\\\\\""'""") + test.run_gyp('defines-escaping.gyp') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines-escaping.c') +test.build('defines-escaping.gyp') + +expect = r""" +\"1 visible slash\" +\\"2 visible slashes\\" +\\\"3 visible slashes\\\" +""" +test.run_built_executable('defines_escaping', stdout=expect) + + +# Test that various scary sequences are passed unfettered. +try: + os.environ['GYP_DEFINES'] = ( + r"""test_format='\n%s\n' """ + r"""test_args='"$foo, " `foo`;"'""") + test.run_gyp('defines-escaping.gyp') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines-escaping.c') +test.build('defines-escaping.gyp') + +expect = """ +$foo, " `foo`; +""" +test.run_built_executable('defines_escaping', stdout=expect) + + +# VisualStudio 2010 can't handle passing %PATH% +if not (test.format == 'msvs' and test.uses_msbuild): + try: + os.environ['GYP_DEFINES'] = ( + """test_format='%s' """ + """test_args='"%PATH%"'""") + test.run_gyp('defines-escaping.gyp') + finally: + del os.environ['GYP_DEFINES'] + + test.sleep() + test.touch('defines-escaping.c') + test.build('defines-escaping.gyp') + + expect = "%PATH%" + test.run_built_executable('defines_escaping', stdout=expect) + + +# Test commas and semi-colons preceded by backslashes (to exercise Windows' +# quoting behaviour). +try: + os.environ['GYP_DEFINES'] = ( + r"""test_format='\n%s\n%s\n' """ + r"""test_args='"\\, \\\\;",""" + # Same thing again, but enclosed in visible quotes. + r""" "\"\\, \\\\;\""'""") + test.run_gyp('defines-escaping.gyp') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines-escaping.c') +test.build('defines-escaping.gyp') + +expect = r""" +\, \\; +"\, \\;" +""" +test.run_built_executable('defines_escaping', stdout=expect) + +# We deliberately do not test having an odd number of quotes in a string +# literal because that isn't feasible in MSVS. + +test.pass_test() diff --git a/tools/gyp/test/defines/defines-env.gyp b/tools/gyp/test/defines/defines-env.gyp new file mode 100644 index 00000000000000..1781546ae0871c --- /dev/null +++ b/tools/gyp/test/defines/defines-env.gyp @@ -0,0 +1,22 @@ +# 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. + +{ + 'variables': { + 'value%': '5', + }, + 'targets': [ + { + 'target_name': 'defines', + 'type': 'executable', + 'sources': [ + 'defines.c', + ], + 'defines': [ + 'VALUE=<(value)', + ], + }, + ], +} + diff --git a/tools/gyp/test/defines/defines.c b/tools/gyp/test/defines/defines.c new file mode 100644 index 00000000000000..dda139275df945 --- /dev/null +++ b/tools/gyp/test/defines/defines.c @@ -0,0 +1,23 @@ +/* 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. */ + +#include + +int main(void) +{ +#ifdef FOO + printf("FOO is defined\n"); +#endif + printf("VALUE is %d\n", VALUE); + +#ifdef PAREN_VALUE + printf("2*PAREN_VALUE is %d\n", 2*PAREN_VALUE); +#endif + +#ifdef HASH_VALUE + printf("HASH_VALUE is %s\n", HASH_VALUE); +#endif + + return 0; +} diff --git a/tools/gyp/test/defines/defines.gyp b/tools/gyp/test/defines/defines.gyp new file mode 100644 index 00000000000000..90a755eb84afe8 --- /dev/null +++ b/tools/gyp/test/defines/defines.gyp @@ -0,0 +1,38 @@ +# 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': 'defines', + 'type': 'executable', + 'sources': [ + 'defines.c', + ], + 'defines': [ + 'FOO', + 'VALUE=1', + 'PAREN_VALUE=(1+2+3)', + 'HASH_VALUE="a#1"', + ], + }, + ], + 'conditions': [ + ['OS=="fakeos"', { + 'targets': [ + { + 'target_name': 'fakeosprogram', + 'type': 'executable', + 'sources': [ + 'defines.c', + ], + 'defines': [ + 'FOO', + 'VALUE=1', + ], + }, + ], + }], + ], +} diff --git a/tools/gyp/test/defines/gyptest-define-override.py b/tools/gyp/test/defines/gyptest-define-override.py new file mode 100644 index 00000000000000..0d8af787f185d2 --- /dev/null +++ b/tools/gyp/test/defines/gyptest-define-override.py @@ -0,0 +1,42 @@ +#!/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 that a default gyp define can be overridden. +""" + +import os +import TestGyp + +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', stderr=expect_stderr) +# Clean up the exe so subsequent tests don't find an old exe. +test.built_file_must_exist('fakeosprogram', type=test.EXECUTABLE, remove=True) + +# Without "OS" override, fokeosprogram shouldn't be built. +test.run_gyp('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', stderr=expect_stderr) +test.built_file_must_exist('fakeosprogram', type=test.EXECUTABLE) + +test.pass_test() diff --git a/tools/gyp/test/defines/gyptest-defines-env-regyp.py b/tools/gyp/test/defines/gyptest-defines-env-regyp.py new file mode 100644 index 00000000000000..f2d931c2f7d768 --- /dev/null +++ b/tools/gyp/test/defines/gyptest-defines-env-regyp.py @@ -0,0 +1,51 @@ +#!/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 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. +""" + +import os +import TestGyp + +# Regenerating build files when a gyp file changes is currently only supported +# by the make generator. +test = TestGyp.TestGyp(formats=['make']) + +try: + os.environ['GYP_DEFINES'] = 'value=50' + test.run_gyp('defines.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. + os.environ['GYP_DEFINES'] = '' + del os.environ['GYP_DEFINES'] + +test.build('defines.gyp') + +expect = """\ +FOO is defined +VALUE is 1 +2*PAREN_VALUE is 12 +HASH_VALUE is a#1 +""" +test.run_built_executable('defines', stdout=expect) + +# Sleep so that the changed gyp file will have a newer timestamp than the +# previously generated build files. +test.sleep() +test.write('defines.gyp', test.read('defines-env.gyp')) + +test.build('defines.gyp', test.ALL) + +expect = """\ +VALUE is 50 +""" +test.run_built_executable('defines', stdout=expect) + +test.pass_test() diff --git a/tools/gyp/test/defines/gyptest-defines-env.py b/tools/gyp/test/defines/gyptest-defines-env.py new file mode 100644 index 00000000000000..6b4e7175a6d4d7 --- /dev/null +++ b/tools/gyp/test/defines/gyptest-defines-env.py @@ -0,0 +1,85 @@ +#!/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 build of an executable with C++ define specified by a gyp define. +""" + +import os +import TestGyp + +test = TestGyp.TestGyp() + +# With the value only given in environment, it should be used. +try: + os.environ['GYP_DEFINES'] = 'value=10' + test.run_gyp('defines-env.gyp') +finally: + del os.environ['GYP_DEFINES'] + +test.build('defines-env.gyp') + +expect = """\ +VALUE is 10 +""" +test.run_built_executable('defines', stdout=expect) + + +# With the value given in both command line and environment, +# command line should take precedence. +try: + os.environ['GYP_DEFINES'] = 'value=20' + test.run_gyp('defines-env.gyp', '-Dvalue=25') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines.c') +test.build('defines-env.gyp') + +expect = """\ +VALUE is 25 +""" +test.run_built_executable('defines', stdout=expect) + + +# With the value only given in environment, it should be ignored if +# --ignore-environment is specified. +try: + os.environ['GYP_DEFINES'] = 'value=30' + test.run_gyp('defines-env.gyp', '--ignore-environment') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines.c') +test.build('defines-env.gyp') + +expect = """\ +VALUE is 5 +""" +test.run_built_executable('defines', stdout=expect) + + +# With the value given in both command line and environment, and +# --ignore-environment also specified, command line should still be used. +try: + os.environ['GYP_DEFINES'] = 'value=40' + test.run_gyp('defines-env.gyp', '--ignore-environment', '-Dvalue=45') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines.c') +test.build('defines-env.gyp') + +expect = """\ +VALUE is 45 +""" +test.run_built_executable('defines', stdout=expect) + + +test.pass_test() diff --git a/tools/gyp/test/defines/gyptest-defines.py b/tools/gyp/test/defines/gyptest-defines.py new file mode 100644 index 00000000000000..77a3af53b989bb --- /dev/null +++ b/tools/gyp/test/defines/gyptest-defines.py @@ -0,0 +1,39 @@ +#!/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 build of an executable with C++ defines. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('defines.gyp') + +expect = """\ +FOO is defined +VALUE is 1 +2*PAREN_VALUE is 12 +""" + +#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 --git a/tools/gyp/test/dependencies/a.c b/tools/gyp/test/dependencies/a.c new file mode 100644 index 00000000000000..3bba111d24eefd --- /dev/null +++ b/tools/gyp/test/dependencies/a.c @@ -0,0 +1,9 @@ +/* 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. */ + +extern int funcB(); + +int funcA() { + return funcB(); +} diff --git a/tools/gyp/test/dependencies/adso/all_dependent_settings_order.gyp b/tools/gyp/test/dependencies/adso/all_dependent_settings_order.gyp new file mode 100644 index 00000000000000..89817d6bbb33da --- /dev/null +++ b/tools/gyp/test/dependencies/adso/all_dependent_settings_order.gyp @@ -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 --git a/tools/gyp/test/dependencies/adso/write_args.py b/tools/gyp/test/dependencies/adso/write_args.py new file mode 100644 index 00000000000000..5e388b8f702f83 --- /dev/null +++ b/tools/gyp/test/dependencies/adso/write_args.py @@ -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], 'w') +f.write(' '.join(sys.argv[2:])) +f.close() diff --git a/tools/gyp/test/dependencies/b/b.c b/tools/gyp/test/dependencies/b/b.c new file mode 100644 index 00000000000000..b5e771bcc77b0b --- /dev/null +++ b/tools/gyp/test/dependencies/b/b.c @@ -0,0 +1,3 @@ +int funcB() { + return 2; +} diff --git a/tools/gyp/test/dependencies/b/b.gyp b/tools/gyp/test/dependencies/b/b.gyp new file mode 100644 index 00000000000000..893dc64d652418 --- /dev/null +++ b/tools/gyp/test/dependencies/b/b.gyp @@ -0,0 +1,22 @@ +# 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': 'b', + 'type': 'static_library', + 'sources': [ + 'b.c', + ], + }, + { + 'target_name': 'b3', + 'type': 'static_library', + 'sources': [ + 'b3.c', + ], + }, + ], +} diff --git a/tools/gyp/test/dependencies/b/b3.c b/tools/gyp/test/dependencies/b/b3.c new file mode 100644 index 00000000000000..287f67ff3151e3 --- /dev/null +++ b/tools/gyp/test/dependencies/b/b3.c @@ -0,0 +1,9 @@ +/* + * 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. + */ + +int funcB() { + return 3; +} diff --git a/tools/gyp/test/dependencies/c/c.c b/tools/gyp/test/dependencies/c/c.c new file mode 100644 index 00000000000000..4949daf3ee1fe1 --- /dev/null +++ b/tools/gyp/test/dependencies/c/c.c @@ -0,0 +1,4 @@ +int funcC() { + return 3 + // Intentional syntax error. This file should never be compiled, so this + // shouldn't be a problem. diff --git a/tools/gyp/test/dependencies/c/c.gyp b/tools/gyp/test/dependencies/c/c.gyp new file mode 100644 index 00000000000000..eabebea9efbf41 --- /dev/null +++ b/tools/gyp/test/dependencies/c/c.gyp @@ -0,0 +1,22 @@ +# 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': 'c_unused', + 'type': 'static_library', + 'sources': [ + 'c.c', + ], + }, + { + 'target_name': 'd', + 'type': 'static_library', + 'sources': [ + 'd.c', + ], + }, + ], +} diff --git a/tools/gyp/test/dependencies/c/d.c b/tools/gyp/test/dependencies/c/d.c new file mode 100644 index 00000000000000..05465fc1af7d0c --- /dev/null +++ b/tools/gyp/test/dependencies/c/d.c @@ -0,0 +1,3 @@ +int funcD() { + return 4; +} diff --git a/tools/gyp/test/dependencies/double_dependency.gyp b/tools/gyp/test/dependencies/double_dependency.gyp new file mode 100644 index 00000000000000..c4a2d00139d942 --- /dev/null +++ b/tools/gyp/test/dependencies/double_dependency.gyp @@ -0,0 +1,23 @@ +# 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': 'double_dependency', + 'type': 'shared_library', + 'dependencies': [ + 'double_dependent.gyp:double_dependent', + ], + 'conditions': [ + ['1==1', { + 'dependencies': [ + 'double_dependent.gyp:*', + ], + }], + ], + }, + ], +} + diff --git a/tools/gyp/test/dependencies/double_dependent.gyp b/tools/gyp/test/dependencies/double_dependent.gyp new file mode 100644 index 00000000000000..334caff723ce8e --- /dev/null +++ b/tools/gyp/test/dependencies/double_dependent.gyp @@ -0,0 +1,12 @@ +# 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': 'double_dependent', + 'type': 'none', + }, + ], +} diff --git a/tools/gyp/test/dependencies/extra_targets.gyp b/tools/gyp/test/dependencies/extra_targets.gyp new file mode 100644 index 00000000000000..c1a26de42281ba --- /dev/null +++ b/tools/gyp/test/dependencies/extra_targets.gyp @@ -0,0 +1,18 @@ +# 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': 'a', + 'type': 'static_library', + 'sources': [ + 'a.c', + ], + # This only depends on the "d" target; other targets in c.gyp + # should not become part of the build (unlike with 'c/c.gyp:*'). + 'dependencies': ['c/c.gyp:d'], + }, + ], +} diff --git a/tools/gyp/test/dependencies/gyptest-all-dependent-settings-order.py b/tools/gyp/test/dependencies/gyptest-all-dependent-settings-order.py new file mode 100644 index 00000000000000..715f322f41960e --- /dev/null +++ b/tools/gyp/test/dependencies/gyptest-all-dependent-settings-order.py @@ -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 --git a/tools/gyp/test/dependencies/gyptest-double-dependency.py b/tools/gyp/test/dependencies/gyptest-double-dependency.py new file mode 100644 index 00000000000000..7692740c54deb4 --- /dev/null +++ b/tools/gyp/test/dependencies/gyptest-double-dependency.py @@ -0,0 +1,19 @@ +#!/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 pulling in a dependency a second time in a conditional works for +shared_library targets. Regression test for http://crbug.com/122588 +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('double_dependency.gyp') + +# If running gyp worked, all is well. +test.pass_test() diff --git a/tools/gyp/test/dependencies/gyptest-extra-targets.py b/tools/gyp/test/dependencies/gyptest-extra-targets.py new file mode 100644 index 00000000000000..09b00d958ba175 --- /dev/null +++ b/tools/gyp/test/dependencies/gyptest-extra-targets.py @@ -0,0 +1,22 @@ +#!/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. + +""" +Verify that dependencies don't pull unused targets into the build. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +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. +test.build('extra_targets.gyp', test.ALL) + +test.pass_test() diff --git a/tools/gyp/test/dependencies/gyptest-indirect-module-dependency.py b/tools/gyp/test/dependencies/gyptest-indirect-module-dependency.py new file mode 100644 index 00000000000000..d001b57e7d4f4c --- /dev/null +++ b/tools/gyp/test/dependencies/gyptest-indirect-module-dependency.py @@ -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. + +""" +Make sure that we cause downstream modules to get built when we depend on the +parent targets. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +CHDIR = 'module-dep' +test.run_gyp('indirect-module-dependency.gyp', chdir=CHDIR) +test.build('indirect-module-dependency.gyp', 'an_exe', chdir=CHDIR) +test.built_file_must_exist( + test.built_file_basename('a_module', test.LOADABLE_MODULE), chdir=CHDIR) + +test.pass_test() diff --git a/tools/gyp/test/dependencies/gyptest-lib-only.py b/tools/gyp/test/dependencies/gyptest-lib-only.py new file mode 100644 index 00000000000000..3a99a7f4aa61e0 --- /dev/null +++ b/tools/gyp/test/dependencies/gyptest-lib-only.py @@ -0,0 +1,39 @@ +#!/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. + +""" +Verify that a link time only dependency will get pulled into the set of built +targets, even if no executable uses it. +""" + +import TestGyp + +import sys + +test = TestGyp.TestGyp() + +test.run_gyp('lib_only.gyp') + +test.build('lib_only.gyp', test.ALL) + +test.built_file_must_exist('a', type=test.STATIC_LIB) + +# TODO(bradnelson/mark): +# On linux and windows a library target will at least pull its link dependencies +# into the generated project, since not doing so confuses users. +# This is not currently implemented on mac, which has the opposite behavior. +if sys.platform == 'darwin': + if test.format == 'xcode': + test.built_file_must_not_exist('b', type=test.STATIC_LIB) + else: + 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; + # for the 'b' library, that is in the 'b' subdirectory. + test.built_file_must_exist('b', type=test.STATIC_LIB, subdir='b') + +test.pass_test() diff --git a/tools/gyp/test/dependencies/gyptest-none-traversal.py b/tools/gyp/test/dependencies/gyptest-none-traversal.py new file mode 100644 index 00000000000000..c09063dad3acbf --- /dev/null +++ b/tools/gyp/test/dependencies/gyptest-none-traversal.py @@ -0,0 +1,25 @@ +#!/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. + +""" +Verify that static library dependencies don't traverse none targets, unless +explicitly specified. +""" + +import TestGyp + +import sys + +test = TestGyp.TestGyp() + +test.run_gyp('none_traversal.gyp') + +test.build('none_traversal.gyp', test.ALL) + +test.run_built_executable('needs_chain', stdout="2\n") +test.run_built_executable('doesnt_need_chain', stdout="3\n") + +test.pass_test() diff --git a/tools/gyp/test/dependencies/gyptest-sharedlib-linksettings.py b/tools/gyp/test/dependencies/gyptest-sharedlib-linksettings.py new file mode 100644 index 00000000000000..87428af459126a --- /dev/null +++ b/tools/gyp/test/dependencies/gyptest-sharedlib-linksettings.py @@ -0,0 +1,21 @@ +#!/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 link_settings in a shared_library are not propagated to targets +that depend on the shared_library, but are used in the shared_library itself. +""" + +import TestGyp +import sys + +CHDIR='sharedlib-linksettings' + +test = TestGyp.TestGyp() +test.run_gyp('test.gyp', chdir=CHDIR) +test.build('test.gyp', test.ALL, chdir=CHDIR) +test.run_built_executable('program', stdout="1\n2\n", chdir=CHDIR) +test.pass_test() diff --git a/tools/gyp/test/dependencies/lib_only.gyp b/tools/gyp/test/dependencies/lib_only.gyp new file mode 100644 index 00000000000000..f6c84dea64ffb8 --- /dev/null +++ b/tools/gyp/test/dependencies/lib_only.gyp @@ -0,0 +1,16 @@ +# 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': 'a', + 'type': 'static_library', + 'sources': [ + 'a.c', + ], + 'dependencies': ['b/b.gyp:b'], + }, + ], +} diff --git a/tools/gyp/test/dependencies/main.c b/tools/gyp/test/dependencies/main.c new file mode 100644 index 00000000000000..185bd482f2b784 --- /dev/null +++ b/tools/gyp/test/dependencies/main.c @@ -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. + */ + +#include + +extern int funcA(); + +int main() { + printf("%d\n", funcA()); + return 0; +} diff --git a/tools/gyp/test/dependencies/module-dep/a.cc b/tools/gyp/test/dependencies/module-dep/a.cc new file mode 100644 index 00000000000000..231fc7a9df57d8 --- /dev/null +++ b/tools/gyp/test/dependencies/module-dep/a.cc @@ -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 some_function() { + return 0; +} diff --git a/tools/gyp/test/dependencies/module-dep/dll.cc b/tools/gyp/test/dependencies/module-dep/dll.cc new file mode 100644 index 00000000000000..e1eea0205b7f61 --- /dev/null +++ b/tools/gyp/test/dependencies/module-dep/dll.cc @@ -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. + +#if defined(_MSC_VER) +__declspec(dllexport) +#endif + void SomeFunction() { +} diff --git a/tools/gyp/test/dependencies/module-dep/exe.cc b/tools/gyp/test/dependencies/module-dep/exe.cc new file mode 100644 index 00000000000000..b3039ace96f3ce --- /dev/null +++ b/tools/gyp/test/dependencies/module-dep/exe.cc @@ -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 --git a/tools/gyp/test/dependencies/module-dep/indirect-module-dependency.gyp b/tools/gyp/test/dependencies/module-dep/indirect-module-dependency.gyp new file mode 100644 index 00000000000000..f3fb5320fe866d --- /dev/null +++ b/tools/gyp/test/dependencies/module-dep/indirect-module-dependency.gyp @@ -0,0 +1,37 @@ +# 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': 'an_exe', + 'type': 'executable', + 'sources': ['exe.cc'], + 'dependencies': [ + 'a_dll', + ], + }, + { + 'target_name': 'a_dll', + 'type': 'shared_library', + 'sources': ['dll.cc'], + 'dependencies': [ + 'a_lib', + ], + }, + { + 'target_name': 'a_lib', + 'type': 'static_library', + 'dependencies': [ + 'a_module', + ], + 'sources': ['a.cc'], + }, + { + 'target_name': 'a_module', + 'type': 'loadable_module', + 'sources': ['a.cc'], + }, + ] +} diff --git a/tools/gyp/test/dependencies/none_traversal.gyp b/tools/gyp/test/dependencies/none_traversal.gyp new file mode 100644 index 00000000000000..3d8ab30aff5a19 --- /dev/null +++ b/tools/gyp/test/dependencies/none_traversal.gyp @@ -0,0 +1,46 @@ +# 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': 'needs_chain', + 'type': 'executable', + 'sources': [ + 'a.c', + 'main.c', + ], + 'dependencies': ['chain'], + }, + { + 'target_name': 'chain', + 'type': 'none', + 'dependencies': ['b/b.gyp:b'], + }, + { + 'target_name': 'doesnt_need_chain', + 'type': 'executable', + 'sources': [ + 'main.c', + ], + 'dependencies': ['no_chain', 'other_chain'], + }, + { + 'target_name': 'no_chain', + 'type': 'none', + 'sources': [ + ], + 'dependencies': ['b/b.gyp:b'], + 'dependencies_traverse': 0, + }, + { + 'target_name': 'other_chain', + 'type': 'static_library', + 'sources': [ + 'a.c', + ], + 'dependencies': ['b/b.gyp:b3'], + }, + ], +} diff --git a/tools/gyp/test/dependencies/sharedlib-linksettings/program.c b/tools/gyp/test/dependencies/sharedlib-linksettings/program.c new file mode 100644 index 00000000000000..b7c15edcd6d55c --- /dev/null +++ b/tools/gyp/test/dependencies/sharedlib-linksettings/program.c @@ -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. + */ + +#include + +/* + * This will fail to compile if TEST_DEFINE was propagated from sharedlib to + * program. + */ +#ifdef TEST_DEFINE +#error TEST_DEFINE is already defined! +#endif + +#define TEST_DEFINE 2 + +extern int staticLibFunc(); + +int main() { + printf("%d\n", staticLibFunc()); + printf("%d\n", TEST_DEFINE); + return 0; +} diff --git a/tools/gyp/test/dependencies/sharedlib-linksettings/sharedlib.c b/tools/gyp/test/dependencies/sharedlib-linksettings/sharedlib.c new file mode 100644 index 00000000000000..3199bccd665407 --- /dev/null +++ b/tools/gyp/test/dependencies/sharedlib-linksettings/sharedlib.c @@ -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. + */ + +#ifdef _WIN32 +__declspec(dllexport) +#endif +int sharedLibFunc() { + /* + * This will fail to compile if TEST_DEFINE was not obtained from sharedlib's + * link_settings. + */ + return TEST_DEFINE; +} diff --git a/tools/gyp/test/dependencies/sharedlib-linksettings/staticlib.c b/tools/gyp/test/dependencies/sharedlib-linksettings/staticlib.c new file mode 100644 index 00000000000000..e889b419fdd8f2 --- /dev/null +++ b/tools/gyp/test/dependencies/sharedlib-linksettings/staticlib.c @@ -0,0 +1,24 @@ +/* + * 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 fail to compile if TEST_DEFINE was propagated from sharedlib to + * staticlib. + */ +#ifdef TEST_DEFINE +#error TEST_DEFINE is defined! +#endif + +#ifdef _WIN32 +__declspec(dllimport) +#else +extern +#endif +int sharedLibFunc(); + +int staticLibFunc() { + return sharedLibFunc(); +} diff --git a/tools/gyp/test/dependencies/sharedlib-linksettings/test.gyp b/tools/gyp/test/dependencies/sharedlib-linksettings/test.gyp new file mode 100644 index 00000000000000..830ce3236d6662 --- /dev/null +++ b/tools/gyp/test/dependencies/sharedlib-linksettings/test.gyp @@ -0,0 +1,37 @@ +# 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. + +{ + 'target_defaults': { + 'allow_sharedlib_linksettings_propagation': 0, + }, + 'targets': [ + { + 'target_name': 'sharedlib', + 'type': 'shared_library', + 'sources': [ 'sharedlib.c' ], + 'link_settings': { + 'defines': [ 'TEST_DEFINE=1' ], + }, + 'conditions': [ + ['OS=="linux"', { + # Support 64-bit shared libs (also works fine for 32-bit). + 'cflags': ['-fPIC'], + }], + ], + }, + { + 'target_name': 'staticlib', + 'type': 'static_library', + 'sources': [ 'staticlib.c' ], + 'dependencies': [ 'sharedlib' ], + }, + { + 'target_name': 'program', + 'type': 'executable', + 'sources': [ 'program.c' ], + 'dependencies': [ 'staticlib' ], + }, + ], +} diff --git a/tools/gyp/test/dependency-copy/gyptest-copy.py b/tools/gyp/test/dependency-copy/gyptest-copy.py new file mode 100644 index 00000000000000..5ba7c73d41327a --- /dev/null +++ b/tools/gyp/test/dependency-copy/gyptest-copy.py @@ -0,0 +1,26 @@ +#!/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 dependencies do the copy step. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('copies.gyp', chdir='src') + +test.build('copies.gyp', 'proj2', chdir='src') + +test.run_built_executable('proj1', + chdir='src', + stdout="Hello from file1.c\n") +test.run_built_executable('proj2', + chdir='src', + stdout="Hello from file2.c\n") + +test.pass_test() diff --git a/tools/gyp/test/dependency-copy/src/copies.gyp b/tools/gyp/test/dependency-copy/src/copies.gyp new file mode 100644 index 00000000000000..4176b18787bea3 --- /dev/null +++ b/tools/gyp/test/dependency-copy/src/copies.gyp @@ -0,0 +1,25 @@ +# 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': 'proj1', + 'type': 'executable', + 'sources': [ + 'file1.c', + ], + }, + { + 'target_name': 'proj2', + 'type': 'executable', + 'sources': [ + 'file2.c', + ], + 'dependencies': [ + 'proj1', + ] + }, + ], +} diff --git a/tools/gyp/test/dependency-copy/src/file1.c b/tools/gyp/test/dependency-copy/src/file1.c new file mode 100644 index 00000000000000..d7c3159186f04a --- /dev/null +++ b/tools/gyp/test/dependency-copy/src/file1.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + printf("Hello from file1.c\n"); + return 0; +} diff --git a/tools/gyp/test/dependency-copy/src/file2.c b/tools/gyp/test/dependency-copy/src/file2.c new file mode 100644 index 00000000000000..cf40f57f949bfe --- /dev/null +++ b/tools/gyp/test/dependency-copy/src/file2.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + printf("Hello from file2.c\n"); + return 0; +} diff --git a/tools/gyp/test/determinism/determinism.gyp b/tools/gyp/test/determinism/determinism.gyp new file mode 100644 index 00000000000000..81346748a13671 --- /dev/null +++ b/tools/gyp/test/determinism/determinism.gyp @@ -0,0 +1,59 @@ +# 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': 'determinism', + 'type': 'none', + 'actions': [ + { + 'action_name': 'depfile_action', + 'inputs': [ + 'input.txt', + ], + 'outputs': [ + 'output.txt', + ], + 'depfile': 'depfile.d', + 'action': [ ] + }, + ], + }, + { + 'target_name': 'determinism2', + 'type': 'none', + 'actions': [ + { + 'action_name': 'depfile_action', + 'inputs': [ + 'input.txt', + ], + 'outputs': [ + 'output.txt', + ], + 'depfile': 'depfile.d', + 'action': [ ] + }, + ], + }, + { + 'target_name': 'determinism3', + 'type': 'none', + 'actions': [ + { + 'action_name': 'depfile_action', + 'inputs': [ + 'input.txt', + ], + 'outputs': [ + 'output.txt', + ], + 'depfile': 'depfile.d', + 'action': [ ] + }, + ], + }, + ], +} diff --git a/tools/gyp/test/determinism/empty-targets.gyp b/tools/gyp/test/determinism/empty-targets.gyp new file mode 100644 index 00000000000000..a4ccdd703c9ef8 --- /dev/null +++ b/tools/gyp/test/determinism/empty-targets.gyp @@ -0,0 +1,32 @@ +# 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': 'empty_target1', + 'type': 'none', + }, + { + 'target_name': 'empty_target2', + 'type': 'none', + }, + { + 'target_name': 'empty_target3', + 'type': 'none', + }, + { + 'target_name': 'empty_target4', + 'type': 'none', + }, + { + 'target_name': 'empty_target5', + 'type': 'none', + }, + { + 'target_name': 'empty_target6', + 'type': 'none', + }, + ], +} diff --git a/tools/gyp/test/determinism/gyptest-determinism.py b/tools/gyp/test/determinism/gyptest-determinism.py new file mode 100644 index 00000000000000..670cb4bc9f5f29 --- /dev/null +++ b/tools/gyp/test/determinism/gyptest-determinism.py @@ -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. + +""" +Verifies builds are the same even with different PYTHONHASHSEEDs. +Tests target_short_names and FlattenToList. +""" + +import os +import sys +import TestGyp + +test = TestGyp.TestGyp() +if test.format == 'ninja': + os.environ["PYTHONHASHSEED"] = "1" + test.run_gyp('determinism.gyp') + base = open(test.built_file_path('build.ninja')).read() + + for i in range(1,5): + os.environ["PYTHONHASHSEED"] = str(i) + test.run_gyp('determinism.gyp') + contents = open(test.built_file_path('build.ninja')).read() + if base != contents: + test.fail_test() + + del os.environ["PYTHONHASHSEED"] + test.pass_test() diff --git a/tools/gyp/test/determinism/gyptest-empty-target-names.py b/tools/gyp/test/determinism/gyptest-empty-target-names.py new file mode 100644 index 00000000000000..cf49f5008484b7 --- /dev/null +++ b/tools/gyp/test/determinism/gyptest-empty-target-names.py @@ -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. + +""" +Verifies builds are the same even with different PYTHONHASHSEEDs. +Tests both solibs and implicit_deps. +""" + +import os +import sys +import TestGyp + +test = TestGyp.TestGyp() +if test.format == 'ninja': + os.environ["PYTHONHASHSEED"] = "1" + test.run_gyp('empty-targets.gyp') + base = open(test.built_file_path('build.ninja')).read() + + for i in range(1,5): + os.environ["PYTHONHASHSEED"] = str(i) + test.run_gyp('empty-targets.gyp') + contents = open(test.built_file_path('build.ninja')).read() + if base != contents: + test.fail_test() + + del os.environ["PYTHONHASHSEED"] + test.pass_test() diff --git a/tools/gyp/test/determinism/gyptest-needed-variables.py b/tools/gyp/test/determinism/gyptest-needed-variables.py new file mode 100644 index 00000000000000..7b97cca0d2dff0 --- /dev/null +++ b/tools/gyp/test/determinism/gyptest-needed-variables.py @@ -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. + +""" +Verifies builds are the same even with different PYTHONHASHSEEDs. +Tests needed_variables. +""" + +import os +import sys +import TestGyp + +test = TestGyp.TestGyp() +if test.format == 'ninja': + os.environ["PYTHONHASHSEED"] = "1" + test.run_gyp('needed-variables.gyp') + base = open(test.built_file_path('test.ninja', subdir='obj')).read() + + for i in range(1,5): + os.environ["PYTHONHASHSEED"] = str(i) + test.run_gyp('needed-variables.gyp') + contents = open(test.built_file_path('test.ninja', subdir='obj')).read() + if base != contents: + test.fail_test() + + del os.environ["PYTHONHASHSEED"] + test.pass_test() diff --git a/tools/gyp/test/determinism/gyptest-solibs.py b/tools/gyp/test/determinism/gyptest-solibs.py new file mode 100644 index 00000000000000..a9c312573bd804 --- /dev/null +++ b/tools/gyp/test/determinism/gyptest-solibs.py @@ -0,0 +1,37 @@ +#!/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 builds are the same even with different PYTHONHASHSEEDs. +Tests all_targets, implicit_deps and solibs. +""" + +from __future__ import print_function + +import os +import sys +import TestGyp + +test = TestGyp.TestGyp() +if test.format == 'ninja': + os.environ["PYTHONHASHSEED"] = "1" + test.run_gyp('solibs.gyp') + base1 = open(test.built_file_path('c.ninja', subdir='obj')).read() + base2 = open(test.built_file_path('build.ninja')).read() + + for i in range(1,5): + os.environ["PYTHONHASHSEED"] = str(i) + test.run_gyp('solibs.gyp') + contents1 = open(test.built_file_path('c.ninja', subdir='obj')).read() + contents2 = open(test.built_file_path('build.ninja')).read() + if base1 != contents1: + test.fail_test() + if base2 != contents2: + print(base2) + test.fail_test() + + del os.environ["PYTHONHASHSEED"] + test.pass_test() diff --git a/tools/gyp/test/determinism/main.cc b/tools/gyp/test/determinism/main.cc new file mode 100644 index 00000000000000..2cd74d3c770a98 --- /dev/null +++ b/tools/gyp/test/determinism/main.cc @@ -0,0 +1,5 @@ +extern int foo(); + +int main() { + return foo(); +} diff --git a/tools/gyp/test/determinism/needed-variables.gyp b/tools/gyp/test/determinism/needed-variables.gyp new file mode 100644 index 00000000000000..022165bebd4e5e --- /dev/null +++ b/tools/gyp/test/determinism/needed-variables.gyp @@ -0,0 +1,33 @@ +# 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': 'executable', + 'sources': ['rule.ext'], + 'rules': [{ + 'rule_name': 'rule', + 'extension': 'ext', + 'inputs': [ 'rule.py', ], + 'action': [ + 'python', + 'rule.py', + '<(RULE_INPUT_ROOT)', + '<(RULE_INPUT_EXT)', + '<(RULE_INPUT_DIRNAME)', + '<(RULE_INPUT_NAME)', + '<(RULE_INPUT_PATH)', + ], + 'outputs': [ 'hello_world.txt' ], + 'sources': ['rule.ext'], + 'message': 'Processing <(RULE_INPUT_PATH)', + 'process_outputs_as_sources': 1, + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }], + }, + ], +} diff --git a/tools/gyp/test/determinism/rule.py b/tools/gyp/test/determinism/rule.py new file mode 100644 index 00000000000000..e18c31455743f4 --- /dev/null +++ b/tools/gyp/test/determinism/rule.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python +# Copyright (c) 2017 Google 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 __future__ import print_function + +print('Hello World') diff --git a/tools/gyp/test/determinism/solib.cc b/tools/gyp/test/determinism/solib.cc new file mode 100644 index 00000000000000..0856cd4e007b2e --- /dev/null +++ b/tools/gyp/test/determinism/solib.cc @@ -0,0 +1,8 @@ +#ifdef _MSC_VER +__declspec(dllexport) +#else +__attribute__((visibility("default"))) +#endif +int foo() { + return 42; +} diff --git a/tools/gyp/test/determinism/solibs.gyp b/tools/gyp/test/determinism/solibs.gyp new file mode 100644 index 00000000000000..9ae3246d6383a3 --- /dev/null +++ b/tools/gyp/test/determinism/solibs.gyp @@ -0,0 +1,32 @@ +# 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. + +# This test both tests solibs and implicit_deps. +{ + 'targets': [ + { + 'target_name': 'a', + 'type': 'shared_library', + 'sources': [ 'solib.cc' ], + }, + { + 'target_name': 'b', + 'type': 'shared_library', + 'sources': [ 'solib.cc' ], + }, + { + 'target_name': 'c', + 'type': 'executable', + 'sources': [ 'main.cc' ], + 'dependencies': [ 'a', 'b' ], + }, + ], + 'conditions': [ + ['OS=="linux"', { + 'target_defaults': { + 'cflags': ['-fPIC'], + }, + }], + ], +} diff --git a/tools/gyp/test/empty-target/empty-target.gyp b/tools/gyp/test/empty-target/empty-target.gyp new file mode 100644 index 00000000000000..feefa2805899cb --- /dev/null +++ b/tools/gyp/test/empty-target/empty-target.gyp @@ -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 --git a/tools/gyp/test/empty-target/gyptest-empty-target.py b/tools/gyp/test/empty-target/gyptest-empty-target.py new file mode 100644 index 00000000000000..ecadd4a87f97e3 --- /dev/null +++ b/tools/gyp/test/empty-target/gyptest-empty-target.py @@ -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 --git a/tools/gyp/test/errors/dependency_cycle.gyp b/tools/gyp/test/errors/dependency_cycle.gyp new file mode 100644 index 00000000000000..eef44bc9eb20e9 --- /dev/null +++ b/tools/gyp/test/errors/dependency_cycle.gyp @@ -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 --git a/tools/gyp/test/errors/duplicate_basenames.gyp b/tools/gyp/test/errors/duplicate_basenames.gyp new file mode 100644 index 00000000000000..b3dceb3949b2b2 --- /dev/null +++ b/tools/gyp/test/errors/duplicate_basenames.gyp @@ -0,0 +1,13 @@ +# 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': 'foo', + 'type': 'static_library', + 'sources': ['foo.c', 'foo.cc'], + }, + ] +} diff --git a/tools/gyp/test/errors/duplicate_node.gyp b/tools/gyp/test/errors/duplicate_node.gyp new file mode 100644 index 00000000000000..d6096096bd804e --- /dev/null +++ b/tools/gyp/test/errors/duplicate_node.gyp @@ -0,0 +1,12 @@ +# 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' : 'foo', 'type': 'executable' }, + ], + 'targets': [ + { 'target_name' : 'bar', 'type': 'executable' }, + ] +} diff --git a/tools/gyp/test/errors/duplicate_rule.gyp b/tools/gyp/test/errors/duplicate_rule.gyp new file mode 100644 index 00000000000000..dab98e96c2b442 --- /dev/null +++ b/tools/gyp/test/errors/duplicate_rule.gyp @@ -0,0 +1,22 @@ +# 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': 'foo', + 'type': 'executable', + 'rules': [ + { + 'rule_name': 'bar', + 'extension': '', + }, + { + 'rule_name': 'bar', + 'extension': '', + }, + ], + }, + ], +} diff --git a/tools/gyp/test/errors/duplicate_targets.gyp b/tools/gyp/test/errors/duplicate_targets.gyp new file mode 100644 index 00000000000000..aec470eefa8a3b --- /dev/null +++ b/tools/gyp/test/errors/duplicate_targets.gyp @@ -0,0 +1,14 @@ +# 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': 'foo' + }, + { + 'target_name': 'foo' + }, + ] +} diff --git a/tools/gyp/test/errors/error_command.gyp b/tools/gyp/test/errors/error_command.gyp new file mode 100644 index 00000000000000..1736fc9882bd31 --- /dev/null +++ b/tools/gyp/test/errors/error_command.gyp @@ -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 func1(void) { + return 42; +} + +int main(void) { + printf("Hello, world!\n"); + printf("%d\n", func1()); + return 0; +} diff --git a/tools/gyp/test/external-cross-compile/gyptest-cross.py b/tools/gyp/test/external-cross-compile/gyptest-cross.py new file mode 100644 index 00000000000000..a837ec57dc7447 --- /dev/null +++ b/tools/gyp/test/external-cross-compile/gyptest-cross.py @@ -0,0 +1,31 @@ +#!/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 actions can be + a source scanner can be used to implement, +cross-compiles (for Native Client at this point). +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('cross.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('cross.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +From test1.cc +From test2.c +From test3.cc +From test4.c +""" +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + + +test.pass_test() diff --git a/tools/gyp/test/external-cross-compile/src/bogus1.cc b/tools/gyp/test/external-cross-compile/src/bogus1.cc new file mode 100644 index 00000000000000..1b8d01199b5ba8 --- /dev/null +++ b/tools/gyp/test/external-cross-compile/src/bogus1.cc @@ -0,0 +1 @@ +From bogus1.cc diff --git a/tools/gyp/test/external-cross-compile/src/bogus2.c b/tools/gyp/test/external-cross-compile/src/bogus2.c new file mode 100644 index 00000000000000..cbf4a123c46e77 --- /dev/null +++ b/tools/gyp/test/external-cross-compile/src/bogus2.c @@ -0,0 +1 @@ +From bogus2.c diff --git a/tools/gyp/test/external-cross-compile/src/cross.gyp b/tools/gyp/test/external-cross-compile/src/cross.gyp new file mode 100644 index 00000000000000..aeda76b5bdf88d --- /dev/null +++ b/tools/gyp/test/external-cross-compile/src/cross.gyp @@ -0,0 +1,83 @@ +# 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. + +{ + 'includes': ['cross_compile.gypi'], + 'target_defaults': { + 'variables': { + 'nix_lame%': 0, + }, + 'target_conditions': [ + ['nix_lame==1', { + 'sources/': [ + ['exclude', 'lame'], + ], + }], + ], + }, + 'targets': [ + { + 'target_name': 'program', + 'type': 'executable', + 'dependencies': [ + 'program_inc', + ], + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + 'sources': [ + 'program.cc', + ], + }, + { + 'target_name': 'program_inc', + 'type': 'none', + 'dependencies': ['cross_program'], + 'actions': [ + { + 'action_name': 'program_inc', + 'inputs': ['<(SHARED_INTERMEDIATE_DIR)/cross_program.fake'], + 'outputs': ['<(SHARED_INTERMEDIATE_DIR)/cross_program.h'], + 'action': ['python', 'tochar.py', '<@(_inputs)', '<@(_outputs)'], + }, + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + { + 'target_name': 'cross_program', + 'type': 'none', + 'variables': { + 'cross': 1, + 'nix_lame': 1, + }, + 'dependencies': ['cross_lib'], + 'sources': [ + 'test1.cc', + 'test2.c', + 'very_lame.cc', + '<(SHARED_INTERMEDIATE_DIR)/cross_lib.fake', + ], + }, + { + 'target_name': 'cross_lib', + 'type': 'none', + 'variables': { + 'cross': 1, + 'nix_lame': 1, + }, + 'sources': [ + 'test3.cc', + 'test4.c', + 'bogus1.cc', + 'bogus2.c', + 'sort_of_lame.cc', + ], + 'sources!': [ + 'bogus1.cc', + 'bogus2.c', + ], + }, + ], +} diff --git a/tools/gyp/test/external-cross-compile/src/cross_compile.gypi b/tools/gyp/test/external-cross-compile/src/cross_compile.gypi new file mode 100644 index 00000000000000..36e651903f5ade --- /dev/null +++ b/tools/gyp/test/external-cross-compile/src/cross_compile.gypi @@ -0,0 +1,23 @@ +{ + 'target_defaults': { + 'variables': { + 'cross%': 0, + }, + 'target_conditions': [ + ['cross==1', { + 'actions': [ + { + 'action_name': 'cross compile >(_target_name)', + 'inputs': ['^@(_sources)'], + 'outputs': ['<(SHARED_INTERMEDIATE_DIR)/>(_target_name).fake'], + 'action': [ + 'python', 'fake_cross.py', '>@(_outputs)', '^@(_sources)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }], + ], + }, +} diff --git a/tools/gyp/test/external-cross-compile/src/fake_cross.py b/tools/gyp/test/external-cross-compile/src/fake_cross.py new file mode 100644 index 00000000000000..05eacc6a6323b6 --- /dev/null +++ b/tools/gyp/test/external-cross-compile/src/fake_cross.py @@ -0,0 +1,18 @@ +#!/usr/bin/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. + +import sys + +fh = open(sys.argv[1], 'w') + +filenames = sys.argv[2:] + +for filename in filenames: + subfile = open(filename) + data = subfile.read() + subfile.close() + fh.write(data) + +fh.close() diff --git a/tools/gyp/test/external-cross-compile/src/program.cc b/tools/gyp/test/external-cross-compile/src/program.cc new file mode 100644 index 00000000000000..5172ae90fefbed --- /dev/null +++ b/tools/gyp/test/external-cross-compile/src/program.cc @@ -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. + */ + +#include + +static char data[] = { +#include "cross_program.h" +}; + +int main(void) { + fwrite(data, 1, sizeof(data), stdout); + return 0; +} diff --git a/tools/gyp/test/external-cross-compile/src/test1.cc b/tools/gyp/test/external-cross-compile/src/test1.cc new file mode 100644 index 00000000000000..b584c31d153015 --- /dev/null +++ b/tools/gyp/test/external-cross-compile/src/test1.cc @@ -0,0 +1 @@ +From test1.cc diff --git a/tools/gyp/test/external-cross-compile/src/test2.c b/tools/gyp/test/external-cross-compile/src/test2.c new file mode 100644 index 00000000000000..367ae19ea0c836 --- /dev/null +++ b/tools/gyp/test/external-cross-compile/src/test2.c @@ -0,0 +1 @@ +From test2.c diff --git a/tools/gyp/test/external-cross-compile/src/test3.cc b/tools/gyp/test/external-cross-compile/src/test3.cc new file mode 100644 index 00000000000000..9eb64735b8a0fe --- /dev/null +++ b/tools/gyp/test/external-cross-compile/src/test3.cc @@ -0,0 +1 @@ +From test3.cc diff --git a/tools/gyp/test/external-cross-compile/src/test4.c b/tools/gyp/test/external-cross-compile/src/test4.c new file mode 100644 index 00000000000000..8ecc33ec16d57a --- /dev/null +++ b/tools/gyp/test/external-cross-compile/src/test4.c @@ -0,0 +1 @@ +From test4.c diff --git a/tools/gyp/test/external-cross-compile/src/tochar.py b/tools/gyp/test/external-cross-compile/src/tochar.py new file mode 100644 index 00000000000000..c0780d984f0e5e --- /dev/null +++ b/tools/gyp/test/external-cross-compile/src/tochar.py @@ -0,0 +1,13 @@ +#!/usr/bin/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. + +import sys + +src = open(sys.argv[1]) +dst = open(sys.argv[2], 'w') +for ch in src.read(): + dst.write('%d,\n' % ord(ch)) +src.close() +dst.close() diff --git a/tools/gyp/test/fixtures/test-charmap.py b/tools/gyp/test/fixtures/test-charmap.py new file mode 100644 index 00000000000000..9d6712f47e1607 --- /dev/null +++ b/tools/gyp/test/fixtures/test-charmap.py @@ -0,0 +1,22 @@ +from __future__ import print_function +import sys +import locale + +def main(): + encoding = locale.getdefaultlocale()[1] + if not encoding: + return False + + # noinspection PyUnresolvedReferences + hasattr(sys, 'setdefaultencoding') and sys.setdefaultencoding(encoding) + textmap = { + 'cp936': u'\u4e2d\u6587', + 'cp1252': u'Lat\u012Bna', + 'cp932': u'\u306b\u307b\u3093\u3054' + } + if encoding in textmap: + print(textmap[encoding]) + return True + +if __name__ == '__main__': + print(main()) diff --git a/tools/gyp/test/generator-output/actions/actions.gyp b/tools/gyp/test/generator-output/actions/actions.gyp new file mode 100644 index 00000000000000..dded59aff3e34f --- /dev/null +++ b/tools/gyp/test/generator-output/actions/actions.gyp @@ -0,0 +1,16 @@ +# 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': 'pull_in_all_actions', + 'type': 'none', + 'dependencies': [ + 'subdir1/executable.gyp:*', + 'subdir2/none.gyp:*', + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/actions/build/README.txt b/tools/gyp/test/generator-output/actions/build/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/actions/subdir1/actions-out/README.txt b/tools/gyp/test/generator-output/actions/subdir1/actions-out/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/subdir1/actions-out/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/actions/subdir1/build/README.txt b/tools/gyp/test/generator-output/actions/subdir1/build/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/subdir1/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/actions/subdir1/executable.gyp b/tools/gyp/test/generator-output/actions/subdir1/executable.gyp new file mode 100644 index 00000000000000..6bdd60a1fb79f3 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/subdir1/executable.gyp @@ -0,0 +1,44 @@ +# 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': 'program', + 'type': 'executable', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'program.c', + ], + 'actions': [ + { + 'action_name': 'make-prog1', + 'inputs': [ + 'make-prog1.py', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/prog1.c', + ], + 'action': [ + 'python', '<(_inputs)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + { + 'action_name': 'make-prog2', + 'inputs': [ + 'make-prog2.py', + ], + 'outputs': [ + 'actions-out/prog2.c', + ], + 'action': [ + 'python', '<(_inputs)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/actions/subdir1/make-prog1.py b/tools/gyp/test/generator-output/actions/subdir1/make-prog1.py new file mode 100644 index 00000000000000..7ea1d8a2d48708 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/subdir1/make-prog1.py @@ -0,0 +1,20 @@ +#!/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 = r""" +#include + +void prog1(void) +{ + printf("Hello from make-prog1.py\n"); +} +""" + +open(sys.argv[1], 'w').write(contents) + +sys.exit(0) diff --git a/tools/gyp/test/generator-output/actions/subdir1/make-prog2.py b/tools/gyp/test/generator-output/actions/subdir1/make-prog2.py new file mode 100644 index 00000000000000..0bfe4973c24c15 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/subdir1/make-prog2.py @@ -0,0 +1,20 @@ +#!/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 = r""" +#include + +void prog2(void) +{ + printf("Hello from make-prog2.py\n"); +} +""" + +open(sys.argv[1], 'w').write(contents) + +sys.exit(0) diff --git a/tools/gyp/test/generator-output/actions/subdir1/program.c b/tools/gyp/test/generator-output/actions/subdir1/program.c new file mode 100644 index 00000000000000..15f0f94ee57f47 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/subdir1/program.c @@ -0,0 +1,12 @@ +#include + +extern void prog1(void); +extern void prog2(void); + +int main(void) +{ + printf("Hello from program.c\n"); + prog1(); + prog2(); + return 0; +} diff --git a/tools/gyp/test/generator-output/actions/subdir2/actions-out/README.txt b/tools/gyp/test/generator-output/actions/subdir2/actions-out/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/subdir2/actions-out/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/actions/subdir2/build/README.txt b/tools/gyp/test/generator-output/actions/subdir2/build/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/subdir2/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/actions/subdir2/make-file.py b/tools/gyp/test/generator-output/actions/subdir2/make-file.py new file mode 100644 index 00000000000000..088a05e0b0cbca --- /dev/null +++ b/tools/gyp/test/generator-output/actions/subdir2/make-file.py @@ -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 = "Hello from make-file.py\n" + +open(sys.argv[1], 'w').write(contents) diff --git a/tools/gyp/test/generator-output/actions/subdir2/none.gyp b/tools/gyp/test/generator-output/actions/subdir2/none.gyp new file mode 100644 index 00000000000000..f98f52753d0ffe --- /dev/null +++ b/tools/gyp/test/generator-output/actions/subdir2/none.gyp @@ -0,0 +1,31 @@ +# 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': 'file', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'actions': [ + { + 'action_name': 'make-file', + 'inputs': [ + 'make-file.py', + ], + 'outputs': [ + 'actions-out/file.out', + # TODO: enhance testing infrastructure to test this + # without having to hard-code the intermediate dir paths. + #'<(INTERMEDIATE_DIR)/file.out', + ], + 'action': [ + 'python', '<(_inputs)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + } + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/copies/build/README.txt b/tools/gyp/test/generator-output/copies/build/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/copies/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/copies/copies-out/README.txt b/tools/gyp/test/generator-output/copies/copies-out/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/copies/copies-out/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/copies/copies.gyp b/tools/gyp/test/generator-output/copies/copies.gyp new file mode 100644 index 00000000000000..479a3d9b6e8b0d --- /dev/null +++ b/tools/gyp/test/generator-output/copies/copies.gyp @@ -0,0 +1,50 @@ +# 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': 'pull_in_subdir', + 'type': 'none', + 'dependencies': [ + 'subdir/subdir.gyp:*', + ], + }, + { + 'target_name': 'copies1', + 'type': 'none', + 'copies': [ + { + 'destination': 'copies-out', + 'files': [ + 'file1', + ], + }, + ], + }, + { + 'target_name': 'copies2', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out', + 'files': [ + 'file2', + ], + }, + ], + }, + # Verify that a null 'files' list doesn't gag the generators. + { + 'target_name': 'copies_null', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-null', + 'files': [], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/copies/file1 b/tools/gyp/test/generator-output/copies/file1 new file mode 100644 index 00000000000000..84d55c5759cf6b --- /dev/null +++ b/tools/gyp/test/generator-output/copies/file1 @@ -0,0 +1 @@ +file1 contents diff --git a/tools/gyp/test/generator-output/copies/file2 b/tools/gyp/test/generator-output/copies/file2 new file mode 100644 index 00000000000000..af1b8ae35db461 --- /dev/null +++ b/tools/gyp/test/generator-output/copies/file2 @@ -0,0 +1 @@ +file2 contents diff --git a/tools/gyp/test/generator-output/copies/subdir/build/README.txt b/tools/gyp/test/generator-output/copies/subdir/build/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/copies/subdir/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/copies/subdir/copies-out/README.txt b/tools/gyp/test/generator-output/copies/subdir/copies-out/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/copies/subdir/copies-out/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/copies/subdir/file3 b/tools/gyp/test/generator-output/copies/subdir/file3 new file mode 100644 index 00000000000000..43f16f35220657 --- /dev/null +++ b/tools/gyp/test/generator-output/copies/subdir/file3 @@ -0,0 +1 @@ +file3 contents diff --git a/tools/gyp/test/generator-output/copies/subdir/file4 b/tools/gyp/test/generator-output/copies/subdir/file4 new file mode 100644 index 00000000000000..5f7270a0847cc6 --- /dev/null +++ b/tools/gyp/test/generator-output/copies/subdir/file4 @@ -0,0 +1 @@ +file4 contents diff --git a/tools/gyp/test/generator-output/copies/subdir/subdir.gyp b/tools/gyp/test/generator-output/copies/subdir/subdir.gyp new file mode 100644 index 00000000000000..af031d283ae452 --- /dev/null +++ b/tools/gyp/test/generator-output/copies/subdir/subdir.gyp @@ -0,0 +1,32 @@ +# 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': 'copies3', + 'type': 'none', + 'copies': [ + { + 'destination': 'copies-out', + 'files': [ + 'file3', + ], + }, + ], + }, + { + 'target_name': 'copies4', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out', + 'files': [ + 'file4', + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/gyptest-actions.py b/tools/gyp/test/generator-output/gyptest-actions.py new file mode 100644 index 00000000000000..47121d0770dc88 --- /dev/null +++ b/tools/gyp/test/generator-output/gyptest-actions.py @@ -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 --generator-output= behavior when using actions. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +# All the generated files should go under 'gypfiles'. The source directory +# ('actions') should be untouched. +test.writable(test.workpath('actions'), False) +test.run_gyp('actions.gyp', + '--generator-output=' + test.workpath('gypfiles'), + chdir='actions') + +test.writable(test.workpath('actions'), True) + +test.relocate('actions', 'relocate/actions') +test.relocate('gypfiles', 'relocate/gypfiles') + +test.writable(test.workpath('relocate/actions'), False) + +# Some of the action outputs use "pure" relative paths (i.e. without prefixes +# like <(INTERMEDIATE_DIR) or <(PROGRAM_DIR)). Even though we are building under +# 'gypfiles', such outputs will still be created relative to the original .gyp +# sources. Projects probably wouldn't normally do this, since it kind of defeats +# the purpose of '--generator-output', but it is supported behaviour. +test.writable(test.workpath('relocate/actions/build'), True) +test.writable(test.workpath('relocate/actions/subdir1/build'), True) +test.writable(test.workpath('relocate/actions/subdir1/actions-out'), True) +test.writable(test.workpath('relocate/actions/subdir2/build'), True) +test.writable(test.workpath('relocate/actions/subdir2/actions-out'), True) + +test.build('actions.gyp', test.ALL, chdir='relocate/gypfiles') + +expect = """\ +Hello from program.c +Hello from make-prog1.py +Hello from make-prog2.py +""" + +if test.format == 'xcode': + chdir = 'relocate/actions/subdir1' +else: + chdir = 'relocate/gypfiles' +test.run_built_executable('program', chdir=chdir, stdout=expect) + +test.must_match('relocate/actions/subdir2/actions-out/file.out', + "Hello from make-file.py\n") + +test.pass_test() diff --git a/tools/gyp/test/generator-output/gyptest-copies.py b/tools/gyp/test/generator-output/gyptest-copies.py new file mode 100644 index 00000000000000..262dfc30faf11c --- /dev/null +++ b/tools/gyp/test/generator-output/gyptest-copies.py @@ -0,0 +1,59 @@ +#!/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 file copies with --generator-output using an explicit build +target of 'all'. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.writable(test.workpath('copies'), False) + +test.run_gyp('copies.gyp', + '--generator-output=' + test.workpath('gypfiles'), + '-G', 'xcode_ninja_target_pattern=^(?!copies_null)', + chdir='copies') + +test.writable(test.workpath('copies'), True) + +test.relocate('copies', 'relocate/copies') +test.relocate('gypfiles', 'relocate/gypfiles') + +test.writable(test.workpath('relocate/copies'), False) + +test.writable(test.workpath('relocate/copies/build'), True) +test.writable(test.workpath('relocate/copies/copies-out'), True) +test.writable(test.workpath('relocate/copies/subdir/build'), True) +test.writable(test.workpath('relocate/copies/subdir/copies-out'), True) + +test.build('copies.gyp', test.ALL, chdir='relocate/gypfiles') + +test.must_match(['relocate', 'copies', 'copies-out', 'file1'], + "file1 contents\n") + +if test.format == 'xcode': + chdir = 'relocate/copies/build' +elif test.format in ['make', 'ninja', 'xcode-ninja', 'cmake']: + chdir = 'relocate/gypfiles/out' +else: + chdir = 'relocate/gypfiles' +test.must_match([chdir, 'Default', 'copies-out', 'file2'], "file2 contents\n") + +test.must_match(['relocate', 'copies', 'subdir', 'copies-out', 'file3'], + "file3 contents\n") + +if test.format == 'xcode': + chdir = 'relocate/copies/subdir/build' +elif test.format in ['make', 'ninja', 'xcode-ninja', 'cmake']: + chdir = 'relocate/gypfiles/out' +else: + chdir = 'relocate/gypfiles' +test.must_match([chdir, 'Default', 'copies-out', 'file4'], "file4 contents\n") + +test.pass_test() diff --git a/tools/gyp/test/generator-output/gyptest-depth.py b/tools/gyp/test/generator-output/gyptest-depth.py new file mode 100644 index 00000000000000..ee59a11f045df7 --- /dev/null +++ b/tools/gyp/test/generator-output/gyptest-depth.py @@ -0,0 +1,58 @@ +#!/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 building a project hierarchy created when the --generator-output= +and --depth= options is used to put the build configuration files in a separate +directory tree. +""" + +import TestGyp +import os + +# This is a regression test for the make generator only. +test = TestGyp.TestGyp(formats=['make']) + +test.writable(test.workpath('src'), False) + +toplevel_dir = os.path.basename(test.workpath()) + +test.run_gyp(os.path.join(toplevel_dir, 'src', 'prog1.gyp'), + '-Dset_symroot=1', + '--generator-output=gypfiles', + depth=toplevel_dir, + chdir='..') + +test.writable(test.workpath('src/build'), True) +test.writable(test.workpath('src/subdir2/build'), True) +test.writable(test.workpath('src/subdir3/build'), True) + +test.build('prog1.gyp', test.ALL, chdir='gypfiles') + +chdir = 'gypfiles' + +expect = """\ +Hello from %s +Hello from inc.h +Hello from inc1/include1.h +Hello from inc2/include2.h +Hello from inc3/include3.h +Hello from subdir2/deeper/deeper.h +""" + +if test.format == 'xcode': + chdir = 'src' +test.run_built_executable('prog1', chdir=chdir, stdout=expect % 'prog1.c') + +if test.format == 'xcode': + chdir = 'src/subdir2' +test.run_built_executable('prog2', chdir=chdir, stdout=expect % 'prog2.c') + +if test.format == 'xcode': + chdir = 'src/subdir3' +test.run_built_executable('prog3', chdir=chdir, stdout=expect % 'prog3.c') + +test.pass_test() diff --git a/tools/gyp/test/generator-output/gyptest-mac-bundle.py b/tools/gyp/test/generator-output/gyptest-mac-bundle.py new file mode 100644 index 00000000000000..14597d8de28832 --- /dev/null +++ b/tools/gyp/test/generator-output/gyptest-mac-bundle.py @@ -0,0 +1,33 @@ +#!/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 mac bundles work with --generator-output. +""" + +from __future__ import print_function + +import TestGyp + +import sys + +if sys.platform == 'darwin': + print("This test is currently disabled: https://crbug.com/483696.") + sys.exit(0) + + test = TestGyp.TestGyp(formats=[]) + + MAC_BUNDLE_DIR = 'mac-bundle' + GYPFILES_DIR = 'gypfiles' + test.writable(test.workpath(MAC_BUNDLE_DIR), False) + test.run_gyp('test.gyp', + '--generator-output=' + test.workpath(GYPFILES_DIR), + chdir=MAC_BUNDLE_DIR) + test.writable(test.workpath(MAC_BUNDLE_DIR), True) + + test.build('test.gyp', test.ALL, chdir=GYPFILES_DIR) + + test.pass_test() diff --git a/tools/gyp/test/generator-output/gyptest-relocate.py b/tools/gyp/test/generator-output/gyptest-relocate.py new file mode 100644 index 00000000000000..b867a6cffb497b --- /dev/null +++ b/tools/gyp/test/generator-output/gyptest-relocate.py @@ -0,0 +1,59 @@ +#!/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 a project hierarchy created with the --generator-output= +option can be built even when it's relocated to a different path. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.writable(test.workpath('src'), False) + +test.run_gyp('prog1.gyp', + '-Dset_symroot=1', + '--generator-output=' + test.workpath('gypfiles'), + chdir='src') + +test.writable(test.workpath('src'), True) + +test.relocate('src', 'relocate/src') +test.relocate('gypfiles', 'relocate/gypfiles') + +test.writable(test.workpath('relocate/src'), False) + +test.writable(test.workpath('relocate/src/build'), True) +test.writable(test.workpath('relocate/src/subdir2/build'), True) +test.writable(test.workpath('relocate/src/subdir3/build'), True) + +test.build('prog1.gyp', test.ALL, chdir='relocate/gypfiles') + +chdir = 'relocate/gypfiles' + +expect = """\ +Hello from %s +Hello from inc.h +Hello from inc1/include1.h +Hello from inc2/include2.h +Hello from inc3/include3.h +Hello from subdir2/deeper/deeper.h +""" + +if test.format == 'xcode': + chdir = 'relocate/src' +test.run_built_executable('prog1', chdir=chdir, stdout=expect % 'prog1.c') + +if test.format == 'xcode': + chdir = 'relocate/src/subdir2' +test.run_built_executable('prog2', chdir=chdir, stdout=expect % 'prog2.c') + +if test.format == 'xcode': + chdir = 'relocate/src/subdir3' +test.run_built_executable('prog3', chdir=chdir, stdout=expect % 'prog3.c') + +test.pass_test() diff --git a/tools/gyp/test/generator-output/gyptest-rules.py b/tools/gyp/test/generator-output/gyptest-rules.py new file mode 100644 index 00000000000000..a3ff8bd858ab8e --- /dev/null +++ b/tools/gyp/test/generator-output/gyptest-rules.py @@ -0,0 +1,58 @@ +#!/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 --generator-output= behavior when using rules. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.writable(test.workpath('rules'), False) + +test.run_gyp('rules.gyp', + '--generator-output=' + test.workpath('gypfiles'), + chdir='rules') + +test.writable(test.workpath('rules'), True) + +test.relocate('rules', 'relocate/rules') +test.relocate('gypfiles', 'relocate/gypfiles') + +test.writable(test.workpath('relocate/rules'), False) + +test.writable(test.workpath('relocate/rules/build'), True) +test.writable(test.workpath('relocate/rules/subdir1/build'), True) +test.writable(test.workpath('relocate/rules/subdir2/build'), True) +test.writable(test.workpath('relocate/rules/subdir2/rules-out'), True) + +test.build('rules.gyp', test.ALL, chdir='relocate/gypfiles') + +expect = """\ +Hello from program.c +Hello from function1.in1 +Hello from function2.in1 +Hello from define3.in0 +Hello from define4.in0 +""" + +if test.format == 'xcode': + chdir = 'relocate/rules/subdir1' +else: + chdir = 'relocate/gypfiles' +test.run_built_executable('program', chdir=chdir, stdout=expect) + +test.must_match('relocate/rules/subdir2/rules-out/file1.out', + "Hello from file1.in0\n") +test.must_match('relocate/rules/subdir2/rules-out/file2.out', + "Hello from file2.in0\n") +test.must_match('relocate/rules/subdir2/rules-out/file3.out', + "Hello from file3.in1\n") +test.must_match('relocate/rules/subdir2/rules-out/file4.out', + "Hello from file4.in1\n") + +test.pass_test() diff --git a/tools/gyp/test/generator-output/gyptest-subdir2-deep.py b/tools/gyp/test/generator-output/gyptest-subdir2-deep.py new file mode 100644 index 00000000000000..ec7862ddd91e2e --- /dev/null +++ b/tools/gyp/test/generator-output/gyptest-subdir2-deep.py @@ -0,0 +1,36 @@ +#!/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 building a target from a .gyp file a few subdirectories +deep when the --generator-output= option is used to put the build +configuration files in a separate directory tree. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.writable(test.workpath('src'), False) + +test.writable(test.workpath('src/subdir2/deeper/build'), True) + +test.run_gyp('deeper.gyp', + '-Dset_symroot=1', + '--generator-output=' + test.workpath('gypfiles'), + chdir='src/subdir2/deeper') + +test.build('deeper.gyp', test.ALL, chdir='gypfiles') + +chdir = 'gypfiles' + +if test.format == 'xcode': + chdir = 'src/subdir2/deeper' +test.run_built_executable('deeper', + chdir=chdir, + stdout="Hello from deeper.c\n") + +test.pass_test() diff --git a/tools/gyp/test/generator-output/gyptest-symlink.py b/tools/gyp/test/generator-output/gyptest-symlink.py new file mode 100644 index 00000000000000..d7fe05830fc3b7 --- /dev/null +++ b/tools/gyp/test/generator-output/gyptest-symlink.py @@ -0,0 +1,44 @@ +#!/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 building a target when the --generator-output= option is used to put +the build configuration files in a separate directory tree referenced by a +symlink. +""" + +import TestGyp +import os +import sys + +test = TestGyp.TestGyp() +if not hasattr(os, 'symlink') or sys.platform == 'win32': + # Python3 on windows has symlink but it doesn't work reliably. + test.skip_test('Missing or bad os.symlink -- skipping test.\n') + +test.writable(test.workpath('src'), False) + +test.writable(test.workpath('src/subdir2/deeper/build'), True) + +test.subdir(test.workpath('build')) +test.subdir(test.workpath('build/deeper')) +test.symlink('build/deeper', test.workpath('symlink')) + +test.writable(test.workpath('build/deeper'), True) +test.run_gyp('deeper.gyp', + '-Dset_symroot=2', + '--generator-output=' + test.workpath('symlink'), + chdir='src/subdir2/deeper') + +chdir = 'symlink' +test.build('deeper.gyp', test.ALL, chdir=chdir) + +if test.format == 'xcode': + chdir = 'src/subdir2/deeper' +test.run_built_executable('deeper', + chdir=chdir, + stdout="Hello from deeper.c\n") +test.pass_test() diff --git a/tools/gyp/test/generator-output/gyptest-top-all.py b/tools/gyp/test/generator-output/gyptest-top-all.py new file mode 100644 index 00000000000000..b1776776ead76a --- /dev/null +++ b/tools/gyp/test/generator-output/gyptest-top-all.py @@ -0,0 +1,53 @@ +#!/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 building a project hierarchy created when the --generator-output= +option is used to put the build configuration files in a separate +directory tree. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.writable(test.workpath('src'), False) + +test.run_gyp('prog1.gyp', + '-Dset_symroot=1', + '--generator-output=' + test.workpath('gypfiles'), + chdir='src') + +test.writable(test.workpath('src/build'), True) +test.writable(test.workpath('src/subdir2/build'), True) +test.writable(test.workpath('src/subdir3/build'), True) + +test.build('prog1.gyp', test.ALL, chdir='gypfiles') + +chdir = 'gypfiles' + +expect = """\ +Hello from %s +Hello from inc.h +Hello from inc1/include1.h +Hello from inc2/include2.h +Hello from inc3/include3.h +Hello from subdir2/deeper/deeper.h +""" + +if test.format == 'xcode': + chdir = 'src' +test.run_built_executable('prog1', chdir=chdir, stdout=expect % 'prog1.c') + +if test.format == 'xcode': + chdir = 'src/subdir2' +test.run_built_executable('prog2', chdir=chdir, stdout=expect % 'prog2.c') + +if test.format == 'xcode': + chdir = 'src/subdir3' +test.run_built_executable('prog3', chdir=chdir, stdout=expect % 'prog3.c') + +test.pass_test() diff --git a/tools/gyp/test/generator-output/mac-bundle/Info.plist b/tools/gyp/test/generator-output/mac-bundle/Info.plist new file mode 100644 index 00000000000000..8cb142e9f5aa52 --- /dev/null +++ b/tools/gyp/test/generator-output/mac-bundle/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.google.${PRODUCT_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ause + CFBundleVersion + 1 + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tools/gyp/test/generator-output/mac-bundle/app.order b/tools/gyp/test/generator-output/mac-bundle/app.order new file mode 100644 index 00000000000000..4eb9e89d39c8b5 --- /dev/null +++ b/tools/gyp/test/generator-output/mac-bundle/app.order @@ -0,0 +1 @@ +_main diff --git a/tools/gyp/test/generator-output/mac-bundle/header.h b/tools/gyp/test/generator-output/mac-bundle/header.h new file mode 100644 index 00000000000000..7ed77751229041 --- /dev/null +++ b/tools/gyp/test/generator-output/mac-bundle/header.h @@ -0,0 +1 @@ +int f(); diff --git a/tools/gyp/test/generator-output/mac-bundle/main.c b/tools/gyp/test/generator-output/mac-bundle/main.c new file mode 100644 index 00000000000000..237c8ce181774d --- /dev/null +++ b/tools/gyp/test/generator-output/mac-bundle/main.c @@ -0,0 +1 @@ +int main() {} diff --git a/tools/gyp/test/generator-output/mac-bundle/resource.sb b/tools/gyp/test/generator-output/mac-bundle/resource.sb new file mode 100644 index 00000000000000..731befc4570d20 --- /dev/null +++ b/tools/gyp/test/generator-output/mac-bundle/resource.sb @@ -0,0 +1 @@ +A text file. diff --git a/tools/gyp/test/generator-output/mac-bundle/test.gyp b/tools/gyp/test/generator-output/mac-bundle/test.gyp new file mode 100644 index 00000000000000..35ac674f6d7d83 --- /dev/null +++ b/tools/gyp/test/generator-output/mac-bundle/test.gyp @@ -0,0 +1,25 @@ +# 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_app', + 'product_name': 'Test App Gyp', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'main.c', + ], + 'mac_bundle_resources': [ + 'resource.sb', + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + 'ORDER_FILE': 'app.order', + 'GCC_PREFIX_HEADER': 'header.h', + 'GCC_PRECOMPILE_PREFIX_HEADER': 'YES', + }, + }, + ], +} diff --git a/tools/gyp/test/generator-output/rules/build/README.txt b/tools/gyp/test/generator-output/rules/build/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/rules/copy-file.py b/tools/gyp/test/generator-output/rules/copy-file.py new file mode 100644 index 00000000000000..80c6749f93793a --- /dev/null +++ b/tools/gyp/test/generator-output/rules/copy-file.py @@ -0,0 +1,12 @@ +#!/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], 'w').write(contents) + +sys.exit(0) diff --git a/tools/gyp/test/generator-output/rules/rules.gyp b/tools/gyp/test/generator-output/rules/rules.gyp new file mode 100644 index 00000000000000..dded59aff3e34f --- /dev/null +++ b/tools/gyp/test/generator-output/rules/rules.gyp @@ -0,0 +1,16 @@ +# 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': 'pull_in_all_actions', + 'type': 'none', + 'dependencies': [ + 'subdir1/executable.gyp:*', + 'subdir2/none.gyp:*', + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/rules/subdir1/build/README.txt b/tools/gyp/test/generator-output/rules/subdir1/build/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir1/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/rules/subdir1/define3.in0 b/tools/gyp/test/generator-output/rules/subdir1/define3.in0 new file mode 100644 index 00000000000000..cc29c643f397ce --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir1/define3.in0 @@ -0,0 +1 @@ +#define STRING3 "Hello from define3.in0\n" diff --git a/tools/gyp/test/generator-output/rules/subdir1/define4.in0 b/tools/gyp/test/generator-output/rules/subdir1/define4.in0 new file mode 100644 index 00000000000000..c9b0467b3287f1 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir1/define4.in0 @@ -0,0 +1 @@ +#define STRING4 "Hello from define4.in0\n" diff --git a/tools/gyp/test/generator-output/rules/subdir1/executable.gyp b/tools/gyp/test/generator-output/rules/subdir1/executable.gyp new file mode 100644 index 00000000000000..42bee4d7467f3e --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir1/executable.gyp @@ -0,0 +1,59 @@ +# 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': 'program', + 'type': 'executable', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'program.c', + 'function1.in1', + 'function2.in1', + 'define3.in0', + 'define4.in0', + ], + 'include_dirs': [ + '<(INTERMEDIATE_DIR)', + ], + 'rules': [ + { + 'rule_name': 'copy_file_0', + 'extension': 'in0', + 'inputs': [ + '../copy-file.py', + ], + 'outputs': [ + # TODO: fix Make to support generated files not + # in a variable-named path like <(INTERMEDIATE_DIR) + #'<(RULE_INPUT_ROOT).c', + '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).h', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 0, + }, + { + 'rule_name': 'copy_file_1', + 'extension': 'in1', + 'inputs': [ + '../copy-file.py', + ], + 'outputs': [ + # TODO: fix Make to support generated files not + # in a variable-named path like <(INTERMEDIATE_DIR) + #'<(RULE_INPUT_ROOT).c', + '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).c', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/rules/subdir1/function1.in1 b/tools/gyp/test/generator-output/rules/subdir1/function1.in1 new file mode 100644 index 00000000000000..545e7ca16bb273 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir1/function1.in1 @@ -0,0 +1,6 @@ +#include + +void function1(void) +{ + printf("Hello from function1.in1\n"); +} diff --git a/tools/gyp/test/generator-output/rules/subdir1/function2.in1 b/tools/gyp/test/generator-output/rules/subdir1/function2.in1 new file mode 100644 index 00000000000000..6bad43f9cf45b2 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir1/function2.in1 @@ -0,0 +1,6 @@ +#include + +void function2(void) +{ + printf("Hello from function2.in1\n"); +} diff --git a/tools/gyp/test/generator-output/rules/subdir1/program.c b/tools/gyp/test/generator-output/rules/subdir1/program.c new file mode 100644 index 00000000000000..56b320632a75cb --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir1/program.c @@ -0,0 +1,18 @@ +#include +#include "define3.h" +#include "define4.h" + +extern void function1(void); +extern void function2(void); +extern void function3(void); +extern void function4(void); + +int main(void) +{ + printf("Hello from program.c\n"); + function1(); + function2(); + printf("%s", STRING3); + printf("%s", STRING4); + return 0; +} diff --git a/tools/gyp/test/generator-output/rules/subdir2/build/README.txt b/tools/gyp/test/generator-output/rules/subdir2/build/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir2/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/rules/subdir2/file1.in0 b/tools/gyp/test/generator-output/rules/subdir2/file1.in0 new file mode 100644 index 00000000000000..7aca64f4ce0fb8 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir2/file1.in0 @@ -0,0 +1 @@ +Hello from file1.in0 diff --git a/tools/gyp/test/generator-output/rules/subdir2/file2.in0 b/tools/gyp/test/generator-output/rules/subdir2/file2.in0 new file mode 100644 index 00000000000000..80a281a2a9a19d --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir2/file2.in0 @@ -0,0 +1 @@ +Hello from file2.in0 diff --git a/tools/gyp/test/generator-output/rules/subdir2/file3.in1 b/tools/gyp/test/generator-output/rules/subdir2/file3.in1 new file mode 100644 index 00000000000000..60ae2e7931136d --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir2/file3.in1 @@ -0,0 +1 @@ +Hello from file3.in1 diff --git a/tools/gyp/test/generator-output/rules/subdir2/file4.in1 b/tools/gyp/test/generator-output/rules/subdir2/file4.in1 new file mode 100644 index 00000000000000..5a3c30720e7af0 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir2/file4.in1 @@ -0,0 +1 @@ +Hello from file4.in1 diff --git a/tools/gyp/test/generator-output/rules/subdir2/none.gyp b/tools/gyp/test/generator-output/rules/subdir2/none.gyp new file mode 100644 index 00000000000000..664cbd9cb75f6c --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir2/none.gyp @@ -0,0 +1,49 @@ +# 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': 'files', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'file1.in0', + 'file2.in0', + 'file3.in1', + 'file4.in1', + ], + 'rules': [ + { + 'rule_name': 'copy_file_0', + 'extension': 'in0', + 'inputs': [ + '../copy-file.py', + ], + 'outputs': [ + 'rules-out/<(RULE_INPUT_ROOT).out', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 0, + }, + { + 'rule_name': 'copy_file_1', + 'extension': 'in1', + 'inputs': [ + '../copy-file.py', + ], + 'outputs': [ + 'rules-out/<(RULE_INPUT_ROOT).out', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/rules/subdir2/rules-out/README.txt b/tools/gyp/test/generator-output/rules/subdir2/rules-out/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir2/rules-out/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/src/build/README.txt b/tools/gyp/test/generator-output/src/build/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/src/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/src/inc.h b/tools/gyp/test/generator-output/src/inc.h new file mode 100644 index 00000000000000..57aa1a5a7443fb --- /dev/null +++ b/tools/gyp/test/generator-output/src/inc.h @@ -0,0 +1 @@ +#define INC_STRING "inc.h" diff --git a/tools/gyp/test/generator-output/src/inc1/include1.h b/tools/gyp/test/generator-output/src/inc1/include1.h new file mode 100644 index 00000000000000..1d59065fc90a72 --- /dev/null +++ b/tools/gyp/test/generator-output/src/inc1/include1.h @@ -0,0 +1 @@ +#define INCLUDE1_STRING "inc1/include1.h" diff --git a/tools/gyp/test/generator-output/src/prog1.c b/tools/gyp/test/generator-output/src/prog1.c new file mode 100644 index 00000000000000..bf7c2a17bd3a8f --- /dev/null +++ b/tools/gyp/test/generator-output/src/prog1.c @@ -0,0 +1,18 @@ +#include + +#include "inc.h" +#include "include1.h" +#include "include2.h" +#include "include3.h" +#include "deeper.h" + +int main(void) +{ + printf("Hello from prog1.c\n"); + printf("Hello from %s\n", INC_STRING); + printf("Hello from %s\n", INCLUDE1_STRING); + printf("Hello from %s\n", INCLUDE2_STRING); + printf("Hello from %s\n", INCLUDE3_STRING); + printf("Hello from %s\n", DEEPER_STRING); + return 0; +} diff --git a/tools/gyp/test/generator-output/src/prog1.gyp b/tools/gyp/test/generator-output/src/prog1.gyp new file mode 100644 index 00000000000000..d50e6fb0a7edd7 --- /dev/null +++ b/tools/gyp/test/generator-output/src/prog1.gyp @@ -0,0 +1,28 @@ +# 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. + +{ + 'includes': [ + 'symroot.gypi', + ], + 'targets': [ + { + 'target_name': 'prog1', + 'type': 'executable', + 'dependencies': [ + 'subdir2/prog2.gyp:prog2', + ], + 'include_dirs': [ + '.', + 'inc1', + 'subdir2/inc2', + 'subdir3/inc3', + 'subdir2/deeper', + ], + 'sources': [ + 'prog1.c', + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/src/subdir2/build/README.txt b/tools/gyp/test/generator-output/src/subdir2/build/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir2/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/src/subdir2/deeper/build/README.txt b/tools/gyp/test/generator-output/src/subdir2/deeper/build/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir2/deeper/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.c b/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.c new file mode 100644 index 00000000000000..843505cd11cd8b --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + printf("Hello from deeper.c\n"); + return 0; +} diff --git a/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.gyp b/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.gyp new file mode 100644 index 00000000000000..86487708723770 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.gyp @@ -0,0 +1,18 @@ +# 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. + +{ + 'includes': [ + '../../symroot.gypi', + ], + 'targets': [ + { + 'target_name': 'deeper', + 'type': 'executable', + 'sources': [ + 'deeper.c', + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.h b/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.h new file mode 100644 index 00000000000000..f6484a0fe58666 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.h @@ -0,0 +1 @@ +#define DEEPER_STRING "subdir2/deeper/deeper.h" diff --git a/tools/gyp/test/generator-output/src/subdir2/inc2/include2.h b/tools/gyp/test/generator-output/src/subdir2/inc2/include2.h new file mode 100644 index 00000000000000..1ccfa5dea79fea --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir2/inc2/include2.h @@ -0,0 +1 @@ +#define INCLUDE2_STRING "inc2/include2.h" diff --git a/tools/gyp/test/generator-output/src/subdir2/prog2.c b/tools/gyp/test/generator-output/src/subdir2/prog2.c new file mode 100644 index 00000000000000..d80d8719843767 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir2/prog2.c @@ -0,0 +1,18 @@ +#include + +#include "inc.h" +#include "include1.h" +#include "include2.h" +#include "include3.h" +#include "deeper.h" + +int main(void) +{ + printf("Hello from prog2.c\n"); + printf("Hello from %s\n", INC_STRING); + printf("Hello from %s\n", INCLUDE1_STRING); + printf("Hello from %s\n", INCLUDE2_STRING); + printf("Hello from %s\n", INCLUDE3_STRING); + printf("Hello from %s\n", DEEPER_STRING); + return 0; +} diff --git a/tools/gyp/test/generator-output/src/subdir2/prog2.gyp b/tools/gyp/test/generator-output/src/subdir2/prog2.gyp new file mode 100644 index 00000000000000..7176ed8be74ef1 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir2/prog2.gyp @@ -0,0 +1,28 @@ +# 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. + +{ + 'includes': [ + '../symroot.gypi', + ], + 'targets': [ + { + 'target_name': 'prog2', + 'type': 'executable', + 'include_dirs': [ + '..', + '../inc1', + 'inc2', + '../subdir3/inc3', + 'deeper', + ], + 'dependencies': [ + '../subdir3/prog3.gyp:prog3', + ], + 'sources': [ + 'prog2.c', + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/src/subdir3/build/README.txt b/tools/gyp/test/generator-output/src/subdir3/build/README.txt new file mode 100644 index 00000000000000..90ef8861931485 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir3/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/src/subdir3/inc3/include3.h b/tools/gyp/test/generator-output/src/subdir3/inc3/include3.h new file mode 100644 index 00000000000000..bf53bf1f0070d9 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir3/inc3/include3.h @@ -0,0 +1 @@ +#define INCLUDE3_STRING "inc3/include3.h" diff --git a/tools/gyp/test/generator-output/src/subdir3/prog3.c b/tools/gyp/test/generator-output/src/subdir3/prog3.c new file mode 100644 index 00000000000000..c72233da193ca2 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir3/prog3.c @@ -0,0 +1,18 @@ +#include + +#include "inc.h" +#include "include1.h" +#include "include2.h" +#include "include3.h" +#include "deeper.h" + +int main(void) +{ + printf("Hello from prog3.c\n"); + printf("Hello from %s\n", INC_STRING); + printf("Hello from %s\n", INCLUDE1_STRING); + printf("Hello from %s\n", INCLUDE2_STRING); + printf("Hello from %s\n", INCLUDE3_STRING); + printf("Hello from %s\n", DEEPER_STRING); + return 0; +} diff --git a/tools/gyp/test/generator-output/src/subdir3/prog3.gyp b/tools/gyp/test/generator-output/src/subdir3/prog3.gyp new file mode 100644 index 00000000000000..46c5e000a27247 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir3/prog3.gyp @@ -0,0 +1,25 @@ +# 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. + +{ + 'includes': [ + '../symroot.gypi', + ], + 'targets': [ + { + 'target_name': 'prog3', + 'type': 'executable', + 'include_dirs': [ + '..', + '../inc1', + '../subdir2/inc2', + 'inc3', + '../subdir2/deeper', + ], + 'sources': [ + 'prog3.c', + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/src/symroot.gypi b/tools/gyp/test/generator-output/src/symroot.gypi new file mode 100644 index 00000000000000..519916427c9f13 --- /dev/null +++ b/tools/gyp/test/generator-output/src/symroot.gypi @@ -0,0 +1,16 @@ +# 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. + +{ + 'variables': { + 'set_symroot%': 0, + }, + 'conditions': [ + ['set_symroot == 1', { + 'xcode_settings': { + 'SYMROOT': '<(DEPTH)/build', + }, + }], + ], +} diff --git a/tools/gyp/test/gyp-defines/defines.gyp b/tools/gyp/test/gyp-defines/defines.gyp new file mode 100644 index 00000000000000..f59bbd20d299a5 --- /dev/null +++ b/tools/gyp/test/gyp-defines/defines.gyp @@ -0,0 +1,26 @@ +# 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_target', + 'type': 'none', + 'actions': [ + { + 'action_name': 'test_action', + 'inputs': [], + 'outputs': [ 'action.txt' ], + 'action': [ + 'python', + 'echo.py', + '<(key)', + '<(_outputs)', + ], + 'msvs_cygwin_shell': 0, + } + ], + }, + ], +} diff --git a/tools/gyp/test/gyp-defines/echo.py b/tools/gyp/test/gyp-defines/echo.py new file mode 100644 index 00000000000000..b85add12f68b3a --- /dev/null +++ b/tools/gyp/test/gyp-defines/echo.py @@ -0,0 +1,11 @@ +#!/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. + +import sys + +f = open(sys.argv[2], 'w+') +f.write(sys.argv[1]) +f.close() diff --git a/tools/gyp/test/gyp-defines/gyptest-multiple-values.py b/tools/gyp/test/gyp-defines/gyptest-multiple-values.py new file mode 100644 index 00000000000000..67735cce6a872b --- /dev/null +++ b/tools/gyp/test/gyp-defines/gyptest-multiple-values.py @@ -0,0 +1,36 @@ +#!/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 when multiple values are supplied for a gyp define, the last one +is used. +""" + +import os +import TestGyp + +test = TestGyp.TestGyp() + +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') + +# The last occurrence of a repeated set should take precedence over other +# 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) +else: + test.build('defines.gyp') +test.must_contain('action.txt', 'repeated_value') + +test.pass_test() diff --git a/tools/gyp/test/gyp-defines/gyptest-regyp.py b/tools/gyp/test/gyp-defines/gyptest-regyp.py new file mode 100644 index 00000000000000..0895d81d4f559e --- /dev/null +++ b/tools/gyp/test/gyp-defines/gyptest-regyp.py @@ -0,0 +1,40 @@ +#!/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 when the same value is repeated for a gyp define, duplicates are +stripped from the regeneration rule. +""" + +import os +import TestGyp + +# Regenerating build files when a gyp file changes is currently only supported +# by the make generator. +test = TestGyp.TestGyp(formats=['make']) + +os.environ['GYP_DEFINES'] = 'key=repeated_value key=value1 key=repeated_value' +test.run_gyp('defines.gyp') +test.build('defines.gyp') + +# The last occurrence of a repeated set should take precedence over other +# values. See gyptest-multiple-values.py. +test.must_contain('action.txt', 'repeated_value') + +# So the regeneration rule needs to use the correct order. +test.must_not_contain( + 'Makefile', '"-Dkey=repeated_value" "-Dkey=value1" "-Dkey=repeated_value"') +test.must_contain('Makefile', '"-Dkey=value1" "-Dkey=repeated_value"') + +# Sleep so that the changed gyp file will have a newer timestamp than the +# previously generated build files. +test.sleep() +os.utime("defines.gyp", None) + +test.build('defines.gyp') +test.must_contain('action.txt', 'repeated_value') + +test.pass_test() diff --git a/tools/gyp/test/hard_dependency/gyptest-exported-hard-dependency.py b/tools/gyp/test/hard_dependency/gyptest-exported-hard-dependency.py new file mode 100644 index 00000000000000..ba515288004199 --- /dev/null +++ b/tools/gyp/test/hard_dependency/gyptest-exported-hard-dependency.py @@ -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. + +""" +Verify that a hard_dependency that is exported is pulled in as a dependency +for a target if the target is a static library and if the generator will +remove dependencies between static libraries. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +if test.format == 'dump_dependency_json': + test.skip_test('Skipping test; dependency JSON does not adjust ' \ + 'static libraries.\n') + +test.run_gyp('hard_dependency.gyp', chdir='src') + +chdir = 'relocate/src' +test.relocate('src', chdir) + +test.build('hard_dependency.gyp', 'c', chdir=chdir) + +# The 'a' static library should be built, as it has actions with side-effects +# that are necessary to compile 'c'. Even though 'c' does not directly depend +# on 'a', because 'a' is a hard_dependency that 'b' exports, 'c' should import +# it as a hard_dependency and ensure it is built before building 'c'. +test.built_file_must_exist('a', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_not_exist('b', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_exist('c', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_not_exist('d', type=test.STATIC_LIB, chdir=chdir) + +test.pass_test() diff --git a/tools/gyp/test/hard_dependency/gyptest-no-exported-hard-dependency.py b/tools/gyp/test/hard_dependency/gyptest-no-exported-hard-dependency.py new file mode 100644 index 00000000000000..10774ca2a0025f --- /dev/null +++ b/tools/gyp/test/hard_dependency/gyptest-no-exported-hard-dependency.py @@ -0,0 +1,36 @@ +#!/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. + +""" +Verify that a hard_dependency that is not exported is not pulled in as a +dependency for a target if the target does not explicitly specify a dependency +and none of its dependencies export the hard_dependency. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +if test.format == 'dump_dependency_json': + test.skip_test('Skipping test; dependency JSON does not adjust ' \ + 'static libaries.\n') + +test.run_gyp('hard_dependency.gyp', chdir='src') + +chdir = 'relocate/src' +test.relocate('src', chdir) + +test.build('hard_dependency.gyp', 'd', chdir=chdir) + +# Because 'c' does not export a hard_dependency, only the target 'd' should +# be built. This is because the 'd' target does not need the generated headers +# in order to be compiled. +test.built_file_must_not_exist('a', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_not_exist('b', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_not_exist('c', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_exist('d', type=test.STATIC_LIB, chdir=chdir) + +test.pass_test() diff --git a/tools/gyp/test/hard_dependency/src/a.c b/tools/gyp/test/hard_dependency/src/a.c new file mode 100644 index 00000000000000..0fa0223c979c96 --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/a.c @@ -0,0 +1,9 @@ +/* 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. */ + +#include "a.h" + +int funcA() { + return 42; +} diff --git a/tools/gyp/test/hard_dependency/src/a.h b/tools/gyp/test/hard_dependency/src/a.h new file mode 100644 index 00000000000000..854a06504ad3d0 --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/a.h @@ -0,0 +1,12 @@ +/* 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. */ + +#ifndef A_H_ +#define A_H_ + +#include "generated.h" + +int funcA(); + +#endif // A_H_ diff --git a/tools/gyp/test/hard_dependency/src/b.c b/tools/gyp/test/hard_dependency/src/b.c new file mode 100644 index 00000000000000..0baace929e95b9 --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/b.c @@ -0,0 +1,9 @@ +/* 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. */ + +#include "a.h" + +int funcB() { + return funcA(); +} diff --git a/tools/gyp/test/hard_dependency/src/b.h b/tools/gyp/test/hard_dependency/src/b.h new file mode 100644 index 00000000000000..22b48cefe206ff --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/b.h @@ -0,0 +1,12 @@ +/* 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. */ + +#ifndef B_H_ +#define B_H_ + +#include "a.h" + +int funcB(); + +#endif // B_H_ diff --git a/tools/gyp/test/hard_dependency/src/c.c b/tools/gyp/test/hard_dependency/src/c.c new file mode 100644 index 00000000000000..7d0068208ec64b --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/c.c @@ -0,0 +1,10 @@ +/* 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. */ + +#include "b.h" +#include "c.h" + +int funcC() { + return funcB(); +} diff --git a/tools/gyp/test/hard_dependency/src/c.h b/tools/gyp/test/hard_dependency/src/c.h new file mode 100644 index 00000000000000..f4ea7fefa2beb5 --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/c.h @@ -0,0 +1,10 @@ +/* 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. */ + +#ifndef C_H_ +#define C_H_ + +int funcC(); + +#endif // C_H_ diff --git a/tools/gyp/test/hard_dependency/src/d.c b/tools/gyp/test/hard_dependency/src/d.c new file mode 100644 index 00000000000000..d016c3ce71899f --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/d.c @@ -0,0 +1,9 @@ +/* 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. */ + +#include "c.h" + +int funcD() { + return funcC(); +} diff --git a/tools/gyp/test/hard_dependency/src/emit.py b/tools/gyp/test/hard_dependency/src/emit.py new file mode 100644 index 00000000000000..8ed12f7393bfa6 --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/emit.py @@ -0,0 +1,11 @@ +#!/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. + +import sys + +f = open(sys.argv[1], 'w') +f.write('/* Hello World */\n') +f.close() diff --git a/tools/gyp/test/hard_dependency/src/hard_dependency.gyp b/tools/gyp/test/hard_dependency/src/hard_dependency.gyp new file mode 100644 index 00000000000000..4479c5f0452e15 --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/hard_dependency.gyp @@ -0,0 +1,78 @@ +# 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': 'a', + 'type': 'static_library', + 'sources': [ + 'a.c', + 'a.h', + ], + 'hard_dependency': 1, + 'actions': [ + { + 'action_name': 'generate_headers', + 'inputs': [ + 'emit.py' + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/generated.h' + ], + 'action': [ + 'python', + 'emit.py', + '<(SHARED_INTERMEDIATE_DIR)/generated.h', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + }, + }, + { + 'target_name': 'b', + 'type': 'static_library', + 'sources': [ + 'b.c', + 'b.h', + ], + 'dependencies': [ + 'a', + ], + 'export_dependent_settings': [ + 'a', + ], + }, + { + 'target_name': 'c', + 'type': 'static_library', + 'sources': [ + 'c.c', + 'c.h', + ], + 'dependencies': [ + 'b', + ], + }, + { + 'target_name': 'd', + 'type': 'static_library', + 'sources': [ + 'd.c', + ], + 'dependencies': [ + 'c', + ], + } + ], +} diff --git a/tools/gyp/test/hello/gyptest-all.py b/tools/gyp/test/hello/gyptest-all.py new file mode 100644 index 00000000000000..1739b6886e9fb0 --- /dev/null +++ b/tools/gyp/test/hello/gyptest-all.py @@ -0,0 +1,24 @@ +#!/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 an explicit build target of 'all'. +""" + +import TestGyp + +test = TestGyp.TestGyp(workdir='workarea_all') + +test.run_gyp('hello.gyp') + +test.build('hello.gyp', test.ALL) + +test.run_built_executable('hello', stdout="Hello, world!\n") + +test.up_to_date('hello.gyp', test.ALL) + +test.pass_test() diff --git a/tools/gyp/test/hello/gyptest-default.py b/tools/gyp/test/hello/gyptest-default.py new file mode 100644 index 00000000000000..22377e7ac50433 --- /dev/null +++ b/tools/gyp/test/hello/gyptest-default.py @@ -0,0 +1,24 @@ +#!/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 the default build target. +""" + +import TestGyp + +test = TestGyp.TestGyp(workdir='workarea_default') + +test.run_gyp('hello.gyp') + +test.build('hello.gyp') + +test.run_built_executable('hello', stdout="Hello, world!\n") + +test.up_to_date('hello.gyp', test.DEFAULT) + +test.pass_test() diff --git a/tools/gyp/test/hello/gyptest-disable-regyp.py b/tools/gyp/test/hello/gyptest-disable-regyp.py new file mode 100644 index 00000000000000..1e4b306674862c --- /dev/null +++ b/tools/gyp/test/hello/gyptest-disable-regyp.py @@ -0,0 +1,32 @@ +#!/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 that Makefiles don't get rebuilt when a source gyp file changes and +the disable_regeneration generator flag is set. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('hello.gyp', '-Gauto_regeneration=0') + +test.build('hello.gyp', test.ALL) + +test.run_built_executable('hello', stdout="Hello, world!\n") + +# Sleep so that the changed gyp file will have a newer timestamp than the +# previously generated build files. +test.sleep() +test.write('hello.gyp', test.read('hello2.gyp')) + +test.build('hello.gyp', test.ALL) + +# Should still be the old executable, as regeneration was disabled. +test.run_built_executable('hello', stdout="Hello, world!\n") + +test.pass_test() diff --git a/tools/gyp/test/hello/gyptest-regyp-output.py b/tools/gyp/test/hello/gyptest-regyp-output.py new file mode 100644 index 00000000000000..fd88a85503a270 --- /dev/null +++ b/tools/gyp/test/hello/gyptest-regyp-output.py @@ -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. + +""" +Verifies that Makefiles get rebuilt when a source gyp file changes and +--generator-output is used. +""" + +import TestGyp + +# Regenerating build files when a gyp file changes is currently only supported +# 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' + +test.run_gyp('hello.gyp', '--generator-output=%s' % CHDIR) + +test.build('hello.gyp', test.ALL, chdir=CHDIR) + +test.run_built_executable('hello', stdout="Hello, world!\n", chdir=CHDIR) + +# Sleep so that the changed gyp file will have a newer timestamp than the +# previously generated build files. +test.sleep() +test.write('hello.gyp', test.read('hello2.gyp')) + +test.build('hello.gyp', test.ALL, chdir=CHDIR) + +test.run_built_executable('hello', stdout="Hello, two!\n", chdir=CHDIR) + +test.pass_test() diff --git a/tools/gyp/test/hello/gyptest-regyp.py b/tools/gyp/test/hello/gyptest-regyp.py new file mode 100644 index 00000000000000..b513edcd07cda6 --- /dev/null +++ b/tools/gyp/test/hello/gyptest-regyp.py @@ -0,0 +1,32 @@ +#!/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 Makefiles get rebuilt when a source gyp file changes. +""" + +import TestGyp + +# Regenerating build files when a gyp file changes is currently only supported +# by the make generator. +test = TestGyp.TestGyp(formats=['make']) + +test.run_gyp('hello.gyp') + +test.build('hello.gyp', test.ALL) + +test.run_built_executable('hello', stdout="Hello, world!\n") + +# Sleep so that the changed gyp file will have a newer timestamp than the +# previously generated build files. +test.sleep() +test.write('hello.gyp', test.read('hello2.gyp')) + +test.build('hello.gyp', test.ALL) + +test.run_built_executable('hello', stdout="Hello, two!\n") + +test.pass_test() diff --git a/tools/gyp/test/hello/gyptest-target.py b/tools/gyp/test/hello/gyptest-target.py new file mode 100644 index 00000000000000..1abaf7057bf8ff --- /dev/null +++ b/tools/gyp/test/hello/gyptest-target.py @@ -0,0 +1,24 @@ +#!/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 an explicit build target of 'hello'. +""" + +import TestGyp + +test = TestGyp.TestGyp(workdir='workarea_target') + +test.run_gyp('hello.gyp') + +test.build('hello.gyp', 'hello') + +test.run_built_executable('hello', stdout="Hello, world!\n") + +test.up_to_date('hello.gyp', 'hello') + +test.pass_test() diff --git a/tools/gyp/test/hello/hello.c b/tools/gyp/test/hello/hello.c new file mode 100644 index 00000000000000..0a4c806019e864 --- /dev/null +++ b/tools/gyp/test/hello/hello.c @@ -0,0 +1,11 @@ +/* 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. */ + +#include + +int main(void) +{ + printf("Hello, world!\n"); + return 0; +} diff --git a/tools/gyp/test/hello/hello.gyp b/tools/gyp/test/hello/hello.gyp new file mode 100644 index 00000000000000..1974d51ccd1934 --- /dev/null +++ b/tools/gyp/test/hello/hello.gyp @@ -0,0 +1,15 @@ +# 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': 'hello', + 'type': 'executable', + 'sources': [ + 'hello.c', + ], + }, + ], +} diff --git a/tools/gyp/test/hello/hello2.c b/tools/gyp/test/hello/hello2.c new file mode 100644 index 00000000000000..b14299cae0d458 --- /dev/null +++ b/tools/gyp/test/hello/hello2.c @@ -0,0 +1,11 @@ +/* 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. */ + +#include + +int main(void) +{ + printf("Hello, two!\n"); + return 0; +} diff --git a/tools/gyp/test/hello/hello2.gyp b/tools/gyp/test/hello/hello2.gyp new file mode 100644 index 00000000000000..25b08caf3cad0e --- /dev/null +++ b/tools/gyp/test/hello/hello2.gyp @@ -0,0 +1,15 @@ +# 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': 'hello', + 'type': 'executable', + 'sources': [ + 'hello2.c', + ], + }, + ], +} diff --git a/tools/gyp/test/home_dot_gyp/gyptest-home-includes-config-arg.py b/tools/gyp/test/home_dot_gyp/gyptest-home-includes-config-arg.py new file mode 100644 index 00000000000000..82e39f9d073a41 --- /dev/null +++ b/tools/gyp/test/home_dot_gyp/gyptest-home-includes-config-arg.py @@ -0,0 +1,31 @@ +#!/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 inclusion of $HOME/.gyp/include.gypi works when --config-dir is +specified. +""" + +import os +import TestGyp + +test = TestGyp.TestGyp() + +os.environ['HOME'] = os.path.abspath('home2') + +test.run_gyp('all.gyp', '--config-dir=~/.gyp_new', chdir='src') + +# After relocating, we should still be able to build (build file shouldn't +# contain relative reference to ~/.gyp/include.gypi) +test.relocate('src', 'relocate/src') + +test.build('all.gyp', test.ALL, chdir='relocate/src') + +test.run_built_executable('printfoo', + chdir='relocate/src', + stdout='FOO is fromhome3\n') + +test.pass_test() diff --git a/tools/gyp/test/home_dot_gyp/gyptest-home-includes-config-env.py b/tools/gyp/test/home_dot_gyp/gyptest-home-includes-config-env.py new file mode 100644 index 00000000000000..6f4b299ede4c74 --- /dev/null +++ b/tools/gyp/test/home_dot_gyp/gyptest-home-includes-config-env.py @@ -0,0 +1,33 @@ +#!/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 inclusion of $HOME/.gyp_new/include.gypi works when GYP_CONFIG_DIR +is set. +""" + +import os +import TestGyp + +test = TestGyp.TestGyp() + +os.environ['HOME'] = os.path.abspath('home') +os.environ['GYP_CONFIG_DIR'] = os.path.join(os.path.abspath('home2'), + '.gyp_new') + +test.run_gyp('all.gyp', chdir='src') + +# After relocating, we should still be able to build (build file shouldn't +# contain relative reference to ~/.gyp_new/include.gypi) +test.relocate('src', 'relocate/src') + +test.build('all.gyp', test.ALL, chdir='relocate/src') + +test.run_built_executable('printfoo', + chdir='relocate/src', + stdout='FOO is fromhome3\n') + +test.pass_test() diff --git a/tools/gyp/test/home_dot_gyp/gyptest-home-includes-regyp.py b/tools/gyp/test/home_dot_gyp/gyptest-home-includes-regyp.py new file mode 100644 index 00000000000000..fdf8b144648380 --- /dev/null +++ b/tools/gyp/test/home_dot_gyp/gyptest-home-includes-regyp.py @@ -0,0 +1,44 @@ +#!/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 inclusion of $HOME/.gyp/include.gypi works properly with relocation +and with regeneration. +""" + +import os +import TestGyp + +# Regenerating build files when a gyp file changes is currently only supported +# by the make generator. +test = TestGyp.TestGyp(formats=['make']) + +os.environ['HOME'] = os.path.abspath('home') + +test.run_gyp('all.gyp', chdir='src') + +# After relocating, we should still be able to build (build file shouldn't +# contain relative reference to ~/.gyp/include.gypi) +test.relocate('src', 'relocate/src') + +test.build('all.gyp', test.ALL, chdir='relocate/src') + +test.run_built_executable('printfoo', + chdir='relocate/src', + stdout='FOO is fromhome\n') + +# Building should notice any changes to ~/.gyp/include.gypi and regyp. +test.sleep() + +test.write('home/.gyp/include.gypi', test.read('home2/.gyp/include.gypi')) + +test.build('all.gyp', test.ALL, chdir='relocate/src') + +test.run_built_executable('printfoo', + chdir='relocate/src', + stdout='FOO is fromhome2\n') + +test.pass_test() diff --git a/tools/gyp/test/home_dot_gyp/gyptest-home-includes.py b/tools/gyp/test/home_dot_gyp/gyptest-home-includes.py new file mode 100644 index 00000000000000..8ad52556becc0f --- /dev/null +++ b/tools/gyp/test/home_dot_gyp/gyptest-home-includes.py @@ -0,0 +1,30 @@ +#!/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 inclusion of $HOME/.gyp/include.gypi works. +""" + +import os +import TestGyp + +test = TestGyp.TestGyp() + +os.environ['HOME'] = os.path.abspath('home') + +test.run_gyp('all.gyp', chdir='src') + +# After relocating, we should still be able to build (build file shouldn't +# contain relative reference to ~/.gyp/include.gypi) +test.relocate('src', 'relocate/src') + +test.build('all.gyp', test.ALL, chdir='relocate/src') + +test.run_built_executable('printfoo', + chdir='relocate/src', + stdout='FOO is fromhome\n') + +test.pass_test() diff --git a/tools/gyp/test/home_dot_gyp/src/all.gyp b/tools/gyp/test/home_dot_gyp/src/all.gyp new file mode 100644 index 00000000000000..14b6aea285993f --- /dev/null +++ b/tools/gyp/test/home_dot_gyp/src/all.gyp @@ -0,0 +1,22 @@ +# 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. + +{ + 'variables': { + 'foo%': '"fromdefault"', + }, + 'targets': [ + { + 'target_name': 'printfoo', + 'type': 'executable', + 'sources': [ + 'printfoo.c', + ], + 'defines': [ + 'FOO=<(foo)', + ], + }, + ], +} + diff --git a/tools/gyp/test/home_dot_gyp/src/printfoo.c b/tools/gyp/test/home_dot_gyp/src/printfoo.c new file mode 100644 index 00000000000000..9bb67181b99a08 --- /dev/null +++ b/tools/gyp/test/home_dot_gyp/src/printfoo.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + printf("FOO is %s\n", FOO); + return 0; +} diff --git a/tools/gyp/test/include_dirs/gyptest-all.py b/tools/gyp/test/include_dirs/gyptest-all.py new file mode 100644 index 00000000000000..d64bc6a9cadb9f --- /dev/null +++ b/tools/gyp/test/include_dirs/gyptest-all.py @@ -0,0 +1,43 @@ +#!/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 use of include_dirs when using an explicit build target of 'all'. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('includes.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('includes.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from includes.c +Hello from inc.h +Hello from include1.h +Hello from subdir/inc2/include2.h +Hello from shadow2/shadow.h +""" +test.run_built_executable('includes', stdout=expect, chdir='relocate/src') + +if test.format == 'xcode': + chdir='relocate/src/subdir' +else: + chdir='relocate/src' + +expect = """\ +Hello from subdir/subdir_includes.c +Hello from subdir/inc.h +Hello from include1.h +Hello from subdir/inc2/include2.h +""" +test.run_built_executable('subdir_includes', stdout=expect, chdir=chdir) + +test.pass_test() diff --git a/tools/gyp/test/include_dirs/gyptest-default.py b/tools/gyp/test/include_dirs/gyptest-default.py new file mode 100644 index 00000000000000..fc6141587e10be --- /dev/null +++ b/tools/gyp/test/include_dirs/gyptest-default.py @@ -0,0 +1,43 @@ +#!/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 use of include_dirs when using the default build target. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('includes.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('includes.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from includes.c +Hello from inc.h +Hello from include1.h +Hello from subdir/inc2/include2.h +Hello from shadow2/shadow.h +""" +test.run_built_executable('includes', stdout=expect, chdir='relocate/src') + +if test.format == 'xcode': + chdir='relocate/src/subdir' +else: + chdir='relocate/src' + +expect = """\ +Hello from subdir/subdir_includes.c +Hello from subdir/inc.h +Hello from include1.h +Hello from subdir/inc2/include2.h +""" +test.run_built_executable('subdir_includes', stdout=expect, chdir=chdir) + +test.pass_test() diff --git a/tools/gyp/test/include_dirs/src/inc.h b/tools/gyp/test/include_dirs/src/inc.h new file mode 100644 index 00000000000000..0398d6915f9a72 --- /dev/null +++ b/tools/gyp/test/include_dirs/src/inc.h @@ -0,0 +1 @@ +#define INC_STRING "inc.h" diff --git a/tools/gyp/test/include_dirs/src/inc1/include1.h b/tools/gyp/test/include_dirs/src/inc1/include1.h new file mode 100644 index 00000000000000..43356b5f47a57c --- /dev/null +++ b/tools/gyp/test/include_dirs/src/inc1/include1.h @@ -0,0 +1 @@ +#define INCLUDE1_STRING "include1.h" diff --git a/tools/gyp/test/include_dirs/src/includes.c b/tools/gyp/test/include_dirs/src/includes.c new file mode 100644 index 00000000000000..6e2a23cdffcd1d --- /dev/null +++ b/tools/gyp/test/include_dirs/src/includes.c @@ -0,0 +1,19 @@ +#include + +#include "inc.h" +#include "include1.h" +#include "include2.h" +#include "shadow.h" + +int main(void) +{ + printf("Hello from includes.c\n"); + printf("Hello from %s\n", INC_STRING); + printf("Hello from %s\n", INCLUDE1_STRING); + printf("Hello from %s\n", INCLUDE2_STRING); + /* Test that include_dirs happen first: The gyp file has a -Ishadow1 + cflag and an include_dir of shadow2. Including shadow.h should get + the shadow.h from the include_dir. */ + printf("Hello from %s\n", SHADOW_STRING); + return 0; +} diff --git a/tools/gyp/test/include_dirs/src/includes.gyp b/tools/gyp/test/include_dirs/src/includes.gyp new file mode 100644 index 00000000000000..3592690208aad2 --- /dev/null +++ b/tools/gyp/test/include_dirs/src/includes.gyp @@ -0,0 +1,27 @@ +# 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': 'includes', + 'type': 'executable', + 'dependencies': [ + 'subdir/subdir_includes.gyp:subdir_includes', + ], + 'cflags': [ + '-Ishadow1', + ], + 'include_dirs': [ + '.', + 'inc1', + 'shadow2', + 'subdir/inc2', + ], + 'sources': [ + 'includes.c', + ], + }, + ], +} diff --git a/tools/gyp/test/include_dirs/src/shadow1/shadow.h b/tools/gyp/test/include_dirs/src/shadow1/shadow.h new file mode 100644 index 00000000000000..80f6de20b86c75 --- /dev/null +++ b/tools/gyp/test/include_dirs/src/shadow1/shadow.h @@ -0,0 +1 @@ +#define SHADOW_STRING "shadow1/shadow.h" diff --git a/tools/gyp/test/include_dirs/src/shadow2/shadow.h b/tools/gyp/test/include_dirs/src/shadow2/shadow.h new file mode 100644 index 00000000000000..fad5ccd0856154 --- /dev/null +++ b/tools/gyp/test/include_dirs/src/shadow2/shadow.h @@ -0,0 +1 @@ +#define SHADOW_STRING "shadow2/shadow.h" diff --git a/tools/gyp/test/include_dirs/src/subdir/inc.h b/tools/gyp/test/include_dirs/src/subdir/inc.h new file mode 100644 index 00000000000000..0a68d7b36ad71e --- /dev/null +++ b/tools/gyp/test/include_dirs/src/subdir/inc.h @@ -0,0 +1 @@ +#define INC_STRING "subdir/inc.h" diff --git a/tools/gyp/test/include_dirs/src/subdir/inc2/include2.h b/tools/gyp/test/include_dirs/src/subdir/inc2/include2.h new file mode 100644 index 00000000000000..721577effbdffd --- /dev/null +++ b/tools/gyp/test/include_dirs/src/subdir/inc2/include2.h @@ -0,0 +1 @@ +#define INCLUDE2_STRING "subdir/inc2/include2.h" diff --git a/tools/gyp/test/include_dirs/src/subdir/subdir_includes.c b/tools/gyp/test/include_dirs/src/subdir/subdir_includes.c new file mode 100644 index 00000000000000..4623543c430bc5 --- /dev/null +++ b/tools/gyp/test/include_dirs/src/subdir/subdir_includes.c @@ -0,0 +1,14 @@ +#include + +#include "inc.h" +#include "include1.h" +#include "include2.h" + +int main(void) +{ + printf("Hello from subdir/subdir_includes.c\n"); + printf("Hello from %s\n", INC_STRING); + printf("Hello from %s\n", INCLUDE1_STRING); + printf("Hello from %s\n", INCLUDE2_STRING); + return 0; +} diff --git a/tools/gyp/test/include_dirs/src/subdir/subdir_includes.gyp b/tools/gyp/test/include_dirs/src/subdir/subdir_includes.gyp new file mode 100644 index 00000000000000..257d052c3c920c --- /dev/null +++ b/tools/gyp/test/include_dirs/src/subdir/subdir_includes.gyp @@ -0,0 +1,20 @@ +# 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': 'subdir_includes', + 'type': 'executable', + 'include_dirs': [ + '.', + '../inc1', + 'inc2', + ], + 'sources': [ + 'subdir_includes.c', + ], + }, + ], +} diff --git a/tools/gyp/test/intermediate_dir/gyptest-intermediate-dir.py b/tools/gyp/test/intermediate_dir/gyptest-intermediate-dir.py new file mode 100644 index 00000000000000..bf4b91a2fcd937 --- /dev/null +++ b/tools/gyp/test/intermediate_dir/gyptest-intermediate-dir.py @@ -0,0 +1,44 @@ +#!/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 targets have independent INTERMEDIATE_DIRs. +""" + +import TestGyp + +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') +test.must_contain(intermediate_file1, 'target1') + +shared_intermediate_file1 = test.read('src/shared_outfile.txt') +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') +test.build('test2.gyp', 'target2', chdir='src') +# Check INTERMEDIATE_DIR file didn't get overwritten but SHARED_INTERMEDIATE_DIR +# file did. +intermediate_file2 = test.read('src/outfile.txt') +test.must_contain(intermediate_file1, 'target1') +test.must_contain(intermediate_file2, 'target2') + +shared_intermediate_file2 = test.read('src/shared_outfile.txt') +if shared_intermediate_file1 != shared_intermediate_file2: + test.fail_test(shared_intermediate_file1 + ' != ' + shared_intermediate_file2) + +test.must_contain(shared_intermediate_file1, 'shared_target2') +test.must_contain(shared_intermediate_file2, 'shared_target2') + +test.pass_test() diff --git a/tools/gyp/test/intermediate_dir/src/script.py b/tools/gyp/test/intermediate_dir/src/script.py new file mode 100644 index 00000000000000..2eb73ac206cb43 --- /dev/null +++ b/tools/gyp/test/intermediate_dir/src/script.py @@ -0,0 +1,22 @@ +#!/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. + +# Takes 3 arguments. Writes the 1st argument to the file in the 2nd argument, +# and writes the absolute path to the file in the 2nd argument to the file in +# the 3rd argument. + +import os +import shlex +import sys + +if len(sys.argv) == 3 and ' ' in sys.argv[2]: + sys.argv[2], fourth = shlex.split(sys.argv[2].replace('\\', '\\\\')) + sys.argv.append(fourth) + +with open(sys.argv[2], 'w') as f: + f.write(sys.argv[1]) + +with open(sys.argv[3], 'w') as f: + f.write(os.path.abspath(sys.argv[2])) diff --git a/tools/gyp/test/intermediate_dir/src/shared_infile.txt b/tools/gyp/test/intermediate_dir/src/shared_infile.txt new file mode 100644 index 00000000000000..e2aba15d040934 --- /dev/null +++ b/tools/gyp/test/intermediate_dir/src/shared_infile.txt @@ -0,0 +1 @@ +dummy input diff --git a/tools/gyp/test/intermediate_dir/src/test.gyp b/tools/gyp/test/intermediate_dir/src/test.gyp new file mode 100644 index 00000000000000..b61e7e8ea58342 --- /dev/null +++ b/tools/gyp/test/intermediate_dir/src/test.gyp @@ -0,0 +1,42 @@ +# 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': 'target1', + 'type': 'none', + 'actions': [ + { + 'action_name': 'intermediate', + 'inputs': [], + 'outputs': [ + '<(INTERMEDIATE_DIR)/intermediate_out.txt', + 'outfile.txt', + ], + 'action': [ + 'python', 'script.py', 'target1', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + { + 'action_name': 'shared_intermediate', + 'inputs': [ + 'shared_infile.txt', + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/intermediate_out.txt', + 'shared_outfile.txt', + ], + 'action': [ + 'python', 'script.py', 'shared_target1', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/intermediate_dir/src/test2.gyp b/tools/gyp/test/intermediate_dir/src/test2.gyp new file mode 100644 index 00000000000000..41f5564663e5e1 --- /dev/null +++ b/tools/gyp/test/intermediate_dir/src/test2.gyp @@ -0,0 +1,42 @@ +# 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': 'target2', + 'type': 'none', + 'actions': [ + { + 'action_name': 'intermediate', + 'inputs': [], + 'outputs': [ + '<(INTERMEDIATE_DIR)/intermediate_out.txt', + 'outfile.txt', + ], + 'action': [ + 'python', 'script.py', 'target2', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + { + 'action_name': 'shared_intermediate', + 'inputs': [ + 'shared_infile.txt', + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/intermediate_out.txt', + 'shared_outfile.txt', + ], + 'action': [ + 'python', 'script.py', 'shared_target2', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/ios/app-bundle/TestApp/English.lproj/InfoPlist-error.strings b/tools/gyp/test/ios/app-bundle/TestApp/English.lproj/InfoPlist-error.strings new file mode 100644 index 00000000000000..452e7fabf9dc84 --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/TestApp/English.lproj/InfoPlist-error.strings @@ -0,0 +1,3 @@ +/* Localized versions of Info.plist keys */ + +NSHumanReadableCopyright = "Copyright ©2011 Google Inc." diff --git a/tools/gyp/test/ios/app-bundle/TestApp/English.lproj/InfoPlist.strings b/tools/gyp/test/ios/app-bundle/TestApp/English.lproj/InfoPlist.strings new file mode 100644 index 00000000000000..35bd33a96e6a30 --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/TestApp/English.lproj/InfoPlist.strings @@ -0,0 +1,3 @@ +/* Localized versions of Info.plist keys */ + +NSHumanReadableCopyright = "Copyright ©2011 Google Inc."; diff --git a/tools/gyp/test/ios/app-bundle/TestApp/English.lproj/LanguageMap.plist b/tools/gyp/test/ios/app-bundle/TestApp/English.lproj/LanguageMap.plist new file mode 100644 index 00000000000000..6b948823289a77 --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/TestApp/English.lproj/LanguageMap.plist @@ -0,0 +1,8 @@ + + + + + en + en + + diff --git a/tools/gyp/test/ios/app-bundle/TestApp/English.lproj/MainMenu.xib b/tools/gyp/test/ios/app-bundle/TestApp/English.lproj/MainMenu.xib new file mode 100644 index 00000000000000..21b60448ad7c17 --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/TestApp/English.lproj/MainMenu.xib @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/tools/gyp/test/ios/app-bundle/TestApp/English.lproj/Main_iPhone.storyboard b/tools/gyp/test/ios/app-bundle/TestApp/English.lproj/Main_iPhone.storyboard new file mode 100644 index 00000000000000..723bc851227aac --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/TestApp/English.lproj/Main_iPhone.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/gyp/test/ios/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json b/tools/gyp/test/ios/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000000000..2db2b1c7c6c316 --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json @@ -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 --git a/tools/gyp/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json b/tools/gyp/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json new file mode 100644 index 00000000000000..0a87b6edc67517 --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json @@ -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 diff --git a/tools/gyp/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png b/tools/gyp/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png new file mode 100644 index 0000000000000000000000000000000000000000..0ba769182f117a972f76280a19bd69d6e81b68f7 GIT binary patch literal 3263 zcmV;w3_$aVP)X+uL$Nkc;* zP;zf(X>4Tx07wm;mUmQB*%pV-y*Itk5+Wca^cs2zAksTX6$DXM^`x7XQc?|s+0 z08spb1j2M!0f022SQPH-!CVp(%f$Br7!UytSOLJ{W@ZFO_(THK{JlMynW#v{v-a*T zfMmPdEWc1DbJqWVks>!kBnAKqMb$PuekK>?0+ds;#ThdH1j_W4DKdsJG8Ul;qO2n0 z#IJ1jr{*iW$(WZWsE0n`c;fQ!l&-AnmjxZO1uWyz`0VP>&nP`#itsL#`S=Q!g`M=rU9)45( zJ;-|dRq-b5&z?byo>|{)?5r=n76A4nTALlSzLiw~v~31J<>9PP?;rs31pu_(obw)r zY+jPY;tVGXi|p)da{-@gE-UCa`=5eu%D;v=_nFJ?`&K)q7e9d`Nfk3?MdhZarb|T3 z%nS~f&t(1g5dY)AIcd$w!z`Siz!&j_=v7hZlnI21XuE|xfmo0(WD10T)!}~_HYW!e zew}L+XmwuzeT6wtxJd`dZ#@7*BLgIEKY9Xv>st^p3dp{^Xswa2bB{85{^$B13tWnB z;Y>jyQ|9&zk7RNsqAVGs--K+z0uqo1bf5|}fi5rtEMN^BfHQCd-XH*kfJhJnmIE$G z0%<@5vOzxB0181d*a3EfYH$G5fqKvcPJ%XY23!PJzzuK<41h;K3WmW;Fah3yX$XSw z5EY_9s*o0>51B&N5F1(uc|$=^I1~fLLy3?Ol0f;;Ca4%HgQ}rJP(Ab`bQ-z{U4#0d z2hboi2K@njgb|nm(_szR0JebHusa+GN5aeCM0gdP2N%HG;Yzp`J`T6S7vUT504#-H z!jlL<$Or?`Mpy_N@kBz9SR?@vA#0H$qyni$nvf2p8@Y{0k#Xb$28W?xm>3qu8RLgp zjNxKdVb)?wFx8l2m{v>|<~C*!GlBVnrDD~wrdTJeKXwT=5u1%I#8zOBU|X=4u>;s) z>^mF|$G{ol9B_WP7+f-LHLe7=57&&lfa}8z;U@8Tyei%l?}87(bMRt(A-)QK9Dg3) zj~~XrCy)tR1Z#p1A(kK{Y$Q|=8VKhI{e%(1G*N-5Pjn)N5P8I0VkxnX*g?EW941ba z6iJ387g8iCnY4jaNopcpCOsy-A(P2EWJhusSwLP-t|XrzUnLKcKTwn?CKOLf97RIe zPB}`sKzTrUL#0v;sBY9)s+hW+T2H-1eM)^VN0T#`^Oxhvt&^*fYnAJldnHel*Ozyf zUoM{~Um<@={-*r60#U(0!Bc^wuvVc);k3d%g-J!4qLpHZVwz%!VuRu}#Ze`^l7W)9 z5>Kf>>9Eozr6C$Z)1`URxU@~QI@)F0FdauXr2Es8>BaOP=)Lp_WhG@>R;lZ?BJkMlIuMhw8ApiF&yDYW2hFJ?fJhni{?u z85&g@mo&yT8JcdI$(rSw=QPK(Xj%)k1X|@<=e1rim6`6$RAwc!i#egKuI;BS(LSWz zt39n_sIypSqfWEV6J3%nTQ@-4i zi$R;gsG*9XzhRzXqv2yCs*$VFDx+GXJH|L;wsDH_KI2;^u!)^Xl1YupO;gy^-c(?^ z&$Q1BYvyPsG^;hc$D**@Sy`+`)}T4VJji^bd7Jqw3q6Zii=7tT7GEswEK@D(EFW1Z zSp`^awCb?>!`j4}Yh7b~$A)U-W3$et-R8BesV(1jzwLcHnq9En7Q0Tn&-M=XBKs!$ zF$X<|c!#|X_tWYh)GZit z(Q)Cp9CDE^WG;+fcyOWARoj*0TI>4EP1lX*cEoMO-Pk?Z{kZ!p4@(b`M~lalr<3Oz z&kJ6Nm#vN_+kA5{dW4@^Vjg_`q%qU1ULk& z3Fr!>1V#i_2R;ij2@(Z$1jE4r!MlPVFVbHmT+|iPIq0wy5aS{>yK?9ZAjVh%SOwMWgFjair&;wpi!{CU}&@N=Eg#~ zLQ&zpEzVmGY{hI9Z0+4-0xS$$Xe-OToc?Y*V;rTcf_ zb_jRe-RZjXSeas3UfIyD;9afd%<`i0x4T#DzE)vdabOQ=k7SRuGN`h>O0Q~1)u-yD z>VX=Mn&!Rgd$;YK+Q-}1zu#?t(*cbG#Ronf6db&N$oEidtwC+YVcg-Y!_VuY>bk#Y ze_ww@?MU&F&qswvrN_dLb=5o6*Egs)ls3YRlE$&)amR1{;Ppd$6RYV^Go!iq1UMl% z@#4q$AMc(FJlT1QeX8jv{h#)>&{~RGq1N2iiMFIRX?sk2-|2wUogK~{EkB$8eDsX= znVPf8XG_nK&J~=SIiGia@9y}|z3FhX{g&gcj=lwb=lWgyFW&aLedUh- zof`v-2Kw$UzI*>(+&$@i-u=-BsSjR1%z8NeX#HdC`Hh-Z(6xI-`hmHDqv!v)W&&nrf>M(RhcN6(D;jNN*%^u_SYjF;2ng}*8Ow)d6M ztDk;%`@Lsk$;9w$(d(H%O5UixIr`T2ZRcd@1`!T+Ex66Gv0|`DD_RX93e)DGL?Gqr$&sO&c%f7>^5Ey0KRz*tuAm5S< zS~I2D?1o^NVWmDnh+SKSDE*|YMS*|BYG)?!e=y#G5@MD`YM$ph$?Y>y7&Bm#Lv1s} z^Uo3LI%i^8`a2W2c3}q!qoOao=!TeIaIx(4ncEX)8ULC)mhp*nAFLV1o@oT=y0JU6Ux>sK@8%8rxdN#Dhy|?C0lAB#iLx zjfa_Xa-qpW_p3QFIXEGTa}C^E_3^tE2bczq9!q0sGSwvvXnG)JHcaE`iib%8&zF5P z;^2{-jq{pEQQu+4!qW5*IA-mIgUcTzmdhUAHw`SFj9+UYvt+8zF!nf@AHu2KT-*W^ zW8EU}z1jrEUv-8~fM@Fw&gE!7D&(n)8BFy?xdB!+WuwjT;S(2+zk~>SL8LdU0d6gL zs0`SXsW^VU{$2k+lbbDYXs3WnYTA!b(PYLz?u~rp5{)x7)Y6iuY^qCD5l}L?(-OL- xSlph87|b%bZF8rkbRWg-d|M!n;aFxc>o1aGziX+uL$Nkc;* zP;zf(X>4Tx07wm;mUmQB*%pV-y*Itk5+Wca^cs2zAksTX6$DXM^`x7XQc?|s+0 z08spb1j2M!0f022SQPH-!CVp(%f$Br7!UytSOLJ{W@ZFO_(THK{JlMynW#v{v-a*T zfMmPdEWc1DbJqWVks>!kBnAKqMb$PuekK>?0+ds;#ThdH1j_W4DKdsJG8Ul;qO2n0 z#IJ1jr{*iW$(WZWsE0n`c;fQ!l&-AnmjxZO1uWyz`0VP>&nP`#itsL#`S=Q!g`M=rU9)45( zJ;-|dRq-b5&z?byo>|{)?5r=n76A4nTALlSzLiw~v~31J<>9PP?;rs31pu_(obw)r zY+jPY;tVGXi|p)da{-@gE-UCa`=5eu%D;v=_nFJ?`&K)q7e9d`Nfk3?MdhZarb|T3 z%nS~f&t(1g5dY)AIcd$w!z`Siz!&j_=v7hZlnI21XuE|xfmo0(WD10T)!}~_HYW!e zew}L+XmwuzeT6wtxJd`dZ#@7*BLgIEKY9Xv>st^p3dp{^Xswa2bB{85{^$B13tWnB z;Y>jyQ|9&zk7RNsqAVGs--K+z0uqo1bf5|}fi5rtEMN^BfHQCd-XH*kfJhJnmIE$G z0%<@5vOzxB0181d*a3EfYH$G5fqKvcPJ%XY23!PJzzuK<41h;K3WmW;Fah3yX$XSw z5EY_9s*o0>51B&N5F1(uc|$=^I1~fLLy3?Ol0f;;Ca4%HgQ}rJP(Ab`bQ-z{U4#0d z2hboi2K@njgb|nm(_szR0JebHusa+GN5aeCM0gdP2N%HG;Yzp`J`T6S7vUT504#-H z!jlL<$Or?`Mpy_N@kBz9SR?@vA#0H$qyni$nvf2p8@Y{0k#Xb$28W?xm>3qu8RLgp zjNxKdVb)?wFx8l2m{v>|<~C*!GlBVnrDD~wrdTJeKXwT=5u1%I#8zOBU|X=4u>;s) z>^mF|$G{ol9B_WP7+f-LHLe7=57&&lfa}8z;U@8Tyei%l?}87(bMRt(A-)QK9Dg3) zj~~XrCy)tR1Z#p1A(kK{Y$Q|=8VKhI{e%(1G*N-5Pjn)N5P8I0VkxnX*g?EW941ba z6iJ387g8iCnY4jaNopcpCOsy-A(P2EWJhusSwLP-t|XrzUnLKcKTwn?CKOLf97RIe zPB}`sKzTrUL#0v;sBY9)s+hW+T2H-1eM)^VN0T#`^Oxhvt&^*fYnAJldnHel*Ozyf zUoM{~Um<@={-*r60#U(0!Bc^wuvVc);k3d%g-J!4qLpHZVwz%!VuRu}#Ze`^l7W)9 z5>Kf>>9Eozr6C$Z)1`URxU@~QI@)F0FdauXr2Es8>BaOP=)Lp_WhG@>R;lZ?BJkMlIuMhw8ApiF&yDYW2hFJ?fJhni{?u z85&g@mo&yT8JcdI$(rSw=QPK(Xj%)k1X|@<=e1rim6`6$RAwc!i#egKuI;BS(LSWz zt39n_sIypSqfWEV6J3%nTQ@-4i zi$R;gsG*9XzhRzXqv2yCs*$VFDx+GXJH|L;wsDH_KI2;^u!)^Xl1YupO;gy^-c(?^ z&$Q1BYvyPsG^;hc$D**@Sy`+`)}T4VJji^bd7Jqw3q6Zii=7tT7GEswEK@D(EFW1Z zSp`^awCb?>!`j4}Yh7b~$A)U-W3$et-R8BesV(1jzwLcHnq9En7Q0Tn&-M=XBKs!$ zF$X<|c!#|X_tWYh)GZit z(Q)Cp9CDE^WG;+fcyOWARoj*0TI>4EP1lX*cEoMO-Pk?Z{kZ!p4@(b`M~lalr<3Oz z&kJ6Nm#vN_+kA5{dW4@^Vjg_`q%qU1ULk& z3Fr!>1V#i_2R;ij2@(Z$1jE4r!MlPVFVbHmT+|iPIq0wy5aS{>yK?9ZAjVh%SOwMWgFjair&;wpi!{CU}&@N=Eg#~ zLQ&zpEzVmGY{hI9Z0+4-0xS$$Xe-OToc?Y*V;rTcf_ zb_jRe-RZjXSeas3UfIyD;9afd%<`i0x4T#DzE)vdabOQ=k7SRuGN`h>O0Q~1)u-yD z>VX=Mn&!Rgd$;YK+Q-}1zu#?t(*cbG#Ronf6db&N$oEidtwC+YVcg-Y!_VuY>bk#Y ze_ww@?MU&F&qswvrN_dLb=5o6*Egs)ls3YRlE$&)amR1{;Ppd$6RYV^Go!iq1UMl% z@#4q$AMc(FJlT1QeX8jv{h#)>&{~RGq1N2iiMFIRX?sk2-|2wUogK~{EkB$8eDsX= znVPf8XG_nK&J~=SIiGia@9y}|z3FhX{g&gcj=lwb=lWgyFW&aLedUh- zof`v-2Kw$UzI*>(+&$@i-u=-BsSjR1%z8NeX#HdC`Hh-Z(6xI-`hmHDqv!v)W&&nrf>M(RhcN6(D;jNN*%^u_SYjF;2ng}*8Ow)d6M ztDk;%`@Lsk$;9w$(d(H%O5UixIr`T2ZRcd@TL_}3lqFC*nw=uzyHmf zH4Npgx>PFzzlIi8tXM8Cp*Z!O7aUhYkvm?&rHWsn+7-h(KdI?VwAOS1s)C4V9>YKn@W)hugA2c#_`1qK)izaeFcB16kRlDR%);mY zBY5$(C9qCZkjo1^mMz2Q{nD~C=@1t$TevAi4lxDU!A|_RCxO?6#E=Cf%10{H-D~3b zCfm5KRaq#{Uo>!d%#Ku?y&xk2et0v1fzCQrY7p6jJ}bI{z1wu`>{F2pxiq-4wvCTI ztKh8U4d?y<^q}3*AII)Z8XgS+`tP3xc6|FkpCleEp~I0e1A`ym#mRi|ij_!fcvUjg zl68<^?+ZH8Y!&x|#=LaniizO~q5io?T^XgpCD`pNI|Rwb$sf95Ie;k@FKy6#H<@Kq z9AKz!44<>GD-(y;h~y_I`B*ADm=&-*vCeDW&s^H2_`q?l?iXn~lPfc(gPSG4&O|r6 zj1Gik1k3CXw~O(lD9PnWV1s_^ff>c&GZy-VQ{>5KJ20}^#+3;hQ!^B)9u=Ebvv-QH zzB*IIPj>}klWF7lG+0=?X5eH&MRukC>XdjShK=h(JXzO6apJfseWJ*P_@1%cF?NC! zf@P$RB`}~EJ5|OJ@dFOX1qq8P)XzMnV}HMf$CG|0xo!!AQi% z`9j7xHidUK7ZPeKk6}}I+m*Mv+6pAh_X+uL$Nkc;* zP;zf(X>4Tx07wm;mUmQB*%pV-y*Itk5+Wca^cs2zAksTX6$DXM^`x7XQc?|s+0 z08spb1j2M!0f022SQPH-!CVp(%f$Br7!UytSOLJ{W@ZFO_(THK{JlMynW#v{v-a*T zfMmPdEWc1DbJqWVks>!kBnAKqMb$PuekK>?0+ds;#ThdH1j_W4DKdsJG8Ul;qO2n0 z#IJ1jr{*iW$(WZWsE0n`c;fQ!l&-AnmjxZO1uWyz`0VP>&nP`#itsL#`S=Q!g`M=rU9)45( zJ;-|dRq-b5&z?byo>|{)?5r=n76A4nTALlSzLiw~v~31J<>9PP?;rs31pu_(obw)r zY+jPY;tVGXi|p)da{-@gE-UCa`=5eu%D;v=_nFJ?`&K)q7e9d`Nfk3?MdhZarb|T3 z%nS~f&t(1g5dY)AIcd$w!z`Siz!&j_=v7hZlnI21XuE|xfmo0(WD10T)!}~_HYW!e zew}L+XmwuzeT6wtxJd`dZ#@7*BLgIEKY9Xv>st^p3dp{^Xswa2bB{85{^$B13tWnB z;Y>jyQ|9&zk7RNsqAVGs--K+z0uqo1bf5|}fi5rtEMN^BfHQCd-XH*kfJhJnmIE$G z0%<@5vOzxB0181d*a3EfYH$G5fqKvcPJ%XY23!PJzzuK<41h;K3WmW;Fah3yX$XSw z5EY_9s*o0>51B&N5F1(uc|$=^I1~fLLy3?Ol0f;;Ca4%HgQ}rJP(Ab`bQ-z{U4#0d z2hboi2K@njgb|nm(_szR0JebHusa+GN5aeCM0gdP2N%HG;Yzp`J`T6S7vUT504#-H z!jlL<$Or?`Mpy_N@kBz9SR?@vA#0H$qyni$nvf2p8@Y{0k#Xb$28W?xm>3qu8RLgp zjNxKdVb)?wFx8l2m{v>|<~C*!GlBVnrDD~wrdTJeKXwT=5u1%I#8zOBU|X=4u>;s) z>^mF|$G{ol9B_WP7+f-LHLe7=57&&lfa}8z;U@8Tyei%l?}87(bMRt(A-)QK9Dg3) zj~~XrCy)tR1Z#p1A(kK{Y$Q|=8VKhI{e%(1G*N-5Pjn)N5P8I0VkxnX*g?EW941ba z6iJ387g8iCnY4jaNopcpCOsy-A(P2EWJhusSwLP-t|XrzUnLKcKTwn?CKOLf97RIe zPB}`sKzTrUL#0v;sBY9)s+hW+T2H-1eM)^VN0T#`^Oxhvt&^*fYnAJldnHel*Ozyf zUoM{~Um<@={-*r60#U(0!Bc^wuvVc);k3d%g-J!4qLpHZVwz%!VuRu}#Ze`^l7W)9 z5>Kf>>9Eozr6C$Z)1`URxU@~QI@)F0FdauXr2Es8>BaOP=)Lp_WhG@>R;lZ?BJkMlIuMhw8ApiF&yDYW2hFJ?fJhni{?u z85&g@mo&yT8JcdI$(rSw=QPK(Xj%)k1X|@<=e1rim6`6$RAwc!i#egKuI;BS(LSWz zt39n_sIypSqfWEV6J3%nTQ@-4i zi$R;gsG*9XzhRzXqv2yCs*$VFDx+GXJH|L;wsDH_KI2;^u!)^Xl1YupO;gy^-c(?^ z&$Q1BYvyPsG^;hc$D**@Sy`+`)}T4VJji^bd7Jqw3q6Zii=7tT7GEswEK@D(EFW1Z zSp`^awCb?>!`j4}Yh7b~$A)U-W3$et-R8BesV(1jzwLcHnq9En7Q0Tn&-M=XBKs!$ zF$X<|c!#|X_tWYh)GZit z(Q)Cp9CDE^WG;+fcyOWARoj*0TI>4EP1lX*cEoMO-Pk?Z{kZ!p4@(b`M~lalr<3Oz z&kJ6Nm#vN_+kA5{dW4@^Vjg_`q%qU1ULk& z3Fr!>1V#i_2R;ij2@(Z$1jE4r!MlPVFVbHmT+|iPIq0wy5aS{>yK?9ZAjVh%SOwMWgFjair&;wpi!{CU}&@N=Eg#~ zLQ&zpEzVmGY{hI9Z0+4-0xS$$Xe-OToc?Y*V;rTcf_ zb_jRe-RZjXSeas3UfIyD;9afd%<`i0x4T#DzE)vdabOQ=k7SRuGN`h>O0Q~1)u-yD z>VX=Mn&!Rgd$;YK+Q-}1zu#?t(*cbG#Ronf6db&N$oEidtwC+YVcg-Y!_VuY>bk#Y ze_ww@?MU&F&qswvrN_dLb=5o6*Egs)ls3YRlE$&)amR1{;Ppd$6RYV^Go!iq1UMl% z@#4q$AMc(FJlT1QeX8jv{h#)>&{~RGq1N2iiMFIRX?sk2-|2wUogK~{EkB$8eDsX= znVPf8XG_nK&J~=SIiGia@9y}|z3FhX{g&gcj=lwb=lWgyFW&aLedUh- zof`v-2Kw$UzI*>(+&$@i-u=-BsSjR1%z8NeX#HdC`Hh-Z(6xI-`hmHDqv!v)W&&nrf>M(RhcN6(D;jNN*%^u_SYjF;2ng}*8Ow)d6M ztDk;%`@Lsk$;9w$(d(H%O5UixIr`T2ZRcd@d|TYGF%RT%%>+t<1cSaefa zP!|v(I7yU%EM$pYCQ1;HV4|Y&k+8(5M2v)lpm7G!sEJ^7{vjBApd==n4kdshGfuNP zLNGdXii-@$MuM8b*7bF7uiv?&-EDhM+uNSDcAli|d7t0!JLi1gcW&>IkR;sR{Pzsl z?5ku+S`G=bG!4~~B$X#=lJ_D_(?%r;gV4|)*0cjqmG*C%uRO;CBAFE|X}(bHvb$b{ zBt1suHnTea;XDIcfojGG!C1K{;~HpdYpWwOtrKQ@*6DEd zO@^5@n-sRZgQ37&wx{*kWD07sl4Sy5+;k<(;>`5O4(Dl#7n?RF$d-Z{4h3suW@o9{ zWGBlcW7B;K-Knr7sN${6xXR3fDqac}krP+@xVvbvVK&vBz;s8%8fqBz0wdY@x{W@jH}eJeI#ciEL`Zs#s()U zEvQ8QMFo35@nhcwVLW3x$`N4+8`iq9f{Z|>;rLf$*mNwMX>)G7%n@|%k zdQ!o#nhc|adsjP>Rj^!Ux7;F0gN2JoL2=5Jiy^%BUI0hP3{8X(&@Q2AjT`sRF_*o4 zx|3!(gk8fEt+I)kkCIW35|+>7%&w|pTT49I$RHYawT@x;Z#)Gh;kKK_!4%gMxop!+ zY%HU7t|x%b2tUs6zSaQFah7-0wc=ok>#0n}b#8Muzn|gFp0U1)L#NGMf^stC(~VWL zh>Igkx`n3@N~5l1a-=_}C79%Wq$=fMOw}&2ob->Ma?PIM&b^8DcAt{iCN8J9%ZGb@ zqD<;58kn%WnlOJ`+zfkF4EUljVslx3%VK1a_k=*gK-S5qQIB`NEG?FL}|@8A@>$9`9lC$`Ukk4ke~zq{z%K;V2jlZS)Xe z%`2m5=~8r;G+LApv7u=h=h&H0H+4pV2u}cO>+oYaDYsJ`x0Kbaob5pEM3byy1t+Yd zr{_G6?-;|MJfFpBL!BVcOw4JC0DZL4jcZI~fBc{qn@*&obi#P~O9k&NGlxXy2_Zqu z4AT+L946qlNB&kxjklksIQ1bibw9~!h#^cz!$Hm-oH^Ut5In-76ty)pT+wOx<1h1N zTTS@zW5J|acJszkY_GS0PKL38ysxIa-8lTHi|c)z|5ZVMY^#h@JYADP zhhgmeR>2z{UY9Z!*SqNhC_xRwJ`HxKgbH^mr547=M|rEqI!s|R%!cmm^5gR%^Sx|@ z#)wu-6pAMbh8UQhn;OdD#hkTKOY!No_(c7=$$e@_5FwuK#jJ<+LFSXFi)xeFh zMdDMv14N2Gg$!g5hGh08c_BgMb!_4)>#xn{b=1NQ#<{`o@3{=Kd)-OcR z9fACeS-??d2abq0W7&>A7_6J>vAO$AYt;r>ebo*wUh+E`_ zOVrcS?*wS!4U>vABTJkj_Z^sw5{@eWt7|+=0!$k0LIhoQ+D*w~)ZXl()^5hZIJ1l! k3kfqko<06O8L#5~3mrKpj{Is>w*UYD07*qoM6N<$f?pec9{>OV literal 0 HcmV?d00001 diff --git a/tools/gyp/test/ios/app-bundle/TestApp/TestApp-Info.plist b/tools/gyp/test/ios/app-bundle/TestApp/TestApp-Info.plist new file mode 100644 index 00000000000000..bb900436822995 --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/TestApp/TestApp-Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.google.${PRODUCT_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ause + CFBundleVersion + 1 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tools/gyp/test/ios/app-bundle/TestApp/check_no_signature.py b/tools/gyp/test/ios/app-bundle/TestApp/check_no_signature.py new file mode 100644 index 00000000000000..4f6e340072130b --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/TestApp/check_no_signature.py @@ -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 --git a/tools/gyp/test/ios/app-bundle/TestApp/main.m b/tools/gyp/test/ios/app-bundle/TestApp/main.m new file mode 100644 index 00000000000000..ec93e0e237a18f --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/TestApp/main.m @@ -0,0 +1,13 @@ +// 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. + +#import + +int main(int argc, char *argv[]) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + int retVal = UIApplicationMain(argc, argv, nil, nil); + [pool release]; + return retVal; +} diff --git a/tools/gyp/test/ios/app-bundle/TestApp/only-compile-in-32-bits.m b/tools/gyp/test/ios/app-bundle/TestApp/only-compile-in-32-bits.m new file mode 100644 index 00000000000000..28bb1177881606 --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/TestApp/only-compile-in-32-bits.m @@ -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 --git a/tools/gyp/test/ios/app-bundle/TestApp/only-compile-in-64-bits.m b/tools/gyp/test/ios/app-bundle/TestApp/only-compile-in-64-bits.m new file mode 100644 index 00000000000000..e6d255841875eb --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/TestApp/only-compile-in-64-bits.m @@ -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 --git a/tools/gyp/test/ios/app-bundle/test-archs.gyp b/tools/gyp/test/ios/app-bundle/test-archs.gyp new file mode 100644 index 00000000000000..fa935c4fb43d58 --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/test-archs.gyp @@ -0,0 +1,109 @@ +# 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': { + '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': 'iphoneos', # -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 --git a/tools/gyp/test/ios/app-bundle/test-assets-catalog.gyp b/tools/gyp/test/ios/app-bundle/test-assets-catalog.gyp new file mode 100644 index 00000000000000..9a12d07af7be9e --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/test-assets-catalog.gyp @@ -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 --git a/tools/gyp/test/ios/app-bundle/test-crosscompile.gyp b/tools/gyp/test/ios/app-bundle/test-crosscompile.gyp new file mode 100644 index 00000000000000..d9049588ba3ec9 --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/test-crosscompile.gyp @@ -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 --git a/tools/gyp/test/ios/app-bundle/test-device.gyp b/tools/gyp/test/ios/app-bundle/test-device.gyp new file mode 100644 index 00000000000000..a0cfff7cdb8bc8 --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/test-device.gyp @@ -0,0 +1,109 @@ +# 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)"=="xcode"', { + 'target_defaults': { + 'configurations': { + 'Default': { + 'xcode_settings': { + 'SDKROOT': 'iphonesimulator', + 'CONFIGURATION_BUILD_DIR':'build/Default', + } + }, + 'Default-iphoneos': { + 'xcode_settings': { + 'SDKROOT': 'iphoneos', + 'CONFIGURATION_BUILD_DIR':'build/Default-iphoneos', + } + }, + }, + }, + }, { + 'target_defaults': { + 'configurations': { + 'Default': { + 'xcode_settings': { + 'SDKROOT': 'iphonesimulator', + } + }, + }, + }, + }], + ], + 'targets': [ + { + 'target_name': 'test_app', + 'product_name': 'Test App Gyp', + 'type': 'executable', + '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_OUTPUT_FORMAT':'xml', + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist', + 'IPHONEOS_DEPLOYMENT_TARGET': '8.0', + 'CODE_SIGNING_REQUIRED': 'NO', + 'CODE_SIGN_IDENTITY[sdk=iphoneos*]': '', + + }, + }, + { + 'target_name': 'sig_test', + 'product_name': 'sigtest', + 'type': 'executable', + '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_OUTPUT_FORMAT':'xml', + 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist', + 'IPHONEOS_DEPLOYMENT_TARGET': '8.0', + 'CONFIGURATION_BUILD_DIR':'buildsig/Default', + }, + }, + ], +} diff --git a/tools/gyp/test/ios/app-bundle/test.gyp b/tools/gyp/test/ios/app-bundle/test.gyp new file mode 100644 index 00000000000000..1b2bb0cc90968b --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/test.gyp @@ -0,0 +1,75 @@ +# 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 Gyp', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'TestApp/main.m', + ], + 'mac_bundle_resources': [ + 'TestApp/English.lproj/InfoPlist.strings', + 'TestApp/English.lproj/LanguageMap.plist', + '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', + 'SDKROOT': 'iphonesimulator', # -isysroot + 'IPHONEOS_DEPLOYMENT_TARGET': '7.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 --git a/tools/gyp/test/ios/app-bundle/tool_main.cc b/tools/gyp/test/ios/app-bundle/tool_main.cc new file mode 100644 index 00000000000000..9dc3c94f3431be --- /dev/null +++ b/tools/gyp/test/ios/app-bundle/tool_main.cc @@ -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 --git a/tools/gyp/test/ios/copies-with-xcode-envvars/Info.plist b/tools/gyp/test/ios/copies-with-xcode-envvars/Info.plist new file mode 100644 index 00000000000000..a0985c3e4dbb64 --- /dev/null +++ b/tools/gyp/test/ios/copies-with-xcode-envvars/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/tools/gyp/test/ios/copies-with-xcode-envvars/copies-with-xcode-envvars.gyp b/tools/gyp/test/ios/copies-with-xcode-envvars/copies-with-xcode-envvars.gyp new file mode 100644 index 00000000000000..217dbb047980fb --- /dev/null +++ b/tools/gyp/test/ios/copies-with-xcode-envvars/copies-with-xcode-envvars.gyp @@ -0,0 +1,97 @@ +# Copyright (c) 2016 Mark Callow. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# For testing use of the UI settings & environment variables +# available in Xcode's PBXCopyFilesBuildPhase. +{ + 'targets': [ + { + 'target_name': 'copies-with-xcode-envvars', + 'type': 'executable', + 'mac_bundle': 1, + 'xcode_settings': { + 'SDKROOT': 'iphoneos', + 'TARGETED_DEVICE_FAMILY': '1,2', + 'IPHONEOS_DEPLOYMENT_TARGET': '7.0', + 'CODE_SIGNING_REQUIRED': 'NO', + 'INFOPLIST_FILE': 'Info.plist', + # This is where the test framework looks for results. Without + # this line the result will be in build/Default-iphoneos. + 'CONFIGURATION_BUILD_DIR':'build/Default', + }, + 'sources': [ 'empty.c' ], + 'conditions': [ + ['OS == "ios" or OS == "mac"', { + 'copies': [{ + 'destination': '$(BUILT_PRODUCTS_DIR)', + 'files': [ + 'file0', + ], + }, { + 'destination': '$(BUILT_PRODUCTS_DIR)/$(WRAPPER_NAME)', + 'files': [ + 'file1', + ], + }, { + 'destination': '<(PRODUCT_DIR)/$(EXECUTABLE_FOLDER_PATH)', + 'files': [ + 'file2', + ], + }, { + 'destination': '<(PRODUCT_DIR)/$(UNLOCALIZED_RESOURCES_FOLDER_PATH)', + 'files': [ + 'file3', + ], + }, { + 'destination': '<(PRODUCT_DIR)/$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/testimages', + 'files': [ + 'file4', + ], + }, { + 'destination': '$(BUILT_PRODUCTS_DIR)/$(JAVA_FOLDER_PATH)', + 'files': [ + 'file5', + ], + }, { + 'destination': '<(PRODUCT_DIR)/$(FRAMEWORKS_FOLDER_PATH)', + 'files': [ + 'file6', + ], + }, { + # NOTE: This is not an Xcode macro name but + # xcodeproj_file.py recognizes it and sends + # the output to the same place as + # $(FRAMEWORKS_FOLDER_PATH). xcode_emulation.py + # sets its value to an absolute path. + 'destination': '$(BUILT_FRAMEWORKS_DIR)', + 'files': [ + 'file7', + ], + }, { + 'destination': '<(PRODUCT_DIR)/$(SHARED_FRAMEWORKS_FOLDER_PATH)', + 'files': [ + 'file8', + ], + }, { + 'destination': '<(PRODUCT_DIR)/$(SHARED_SUPPORT_FOLDER_PATH)', + 'files': [ + 'file9', + ], + }, { + 'destination': '<(PRODUCT_DIR)/$(PLUGINS_FOLDER_PATH)', + 'files': [ + 'file10', + ], + }, { + 'destination': '<(PRODUCT_DIR)/$(XPCSERVICES_FOLDER_PATH)', + 'files': [ + 'file11', + ], + }], # copies + }], # OS == "ios" or OS == "mac" + ], # conditions + }], # targets +} + +# vim:ai:ts=4:sts=4:sw=2:expandtab:textwidth=70 diff --git a/tools/gyp/test/ios/copies-with-xcode-envvars/empty.c b/tools/gyp/test/ios/copies-with-xcode-envvars/empty.c new file mode 100644 index 00000000000000..237c8ce181774d --- /dev/null +++ b/tools/gyp/test/ios/copies-with-xcode-envvars/empty.c @@ -0,0 +1 @@ +int main() {} diff --git a/tools/gyp/test/ios/copies-with-xcode-envvars/file0 b/tools/gyp/test/ios/copies-with-xcode-envvars/file0 new file mode 100644 index 00000000000000..117889361f6cbf --- /dev/null +++ b/tools/gyp/test/ios/copies-with-xcode-envvars/file0 @@ -0,0 +1 @@ +file0 contents diff --git a/tools/gyp/test/ios/copies-with-xcode-envvars/file1 b/tools/gyp/test/ios/copies-with-xcode-envvars/file1 new file mode 100644 index 00000000000000..84d55c5759cf6b --- /dev/null +++ b/tools/gyp/test/ios/copies-with-xcode-envvars/file1 @@ -0,0 +1 @@ +file1 contents diff --git a/tools/gyp/test/ios/copies-with-xcode-envvars/file10 b/tools/gyp/test/ios/copies-with-xcode-envvars/file10 new file mode 100644 index 00000000000000..372e992ef9c43f --- /dev/null +++ b/tools/gyp/test/ios/copies-with-xcode-envvars/file10 @@ -0,0 +1 @@ +file10 contents diff --git a/tools/gyp/test/ios/copies-with-xcode-envvars/file11 b/tools/gyp/test/ios/copies-with-xcode-envvars/file11 new file mode 100644 index 00000000000000..923e760e1f1842 --- /dev/null +++ b/tools/gyp/test/ios/copies-with-xcode-envvars/file11 @@ -0,0 +1 @@ +file11 contents diff --git a/tools/gyp/test/ios/copies-with-xcode-envvars/file2 b/tools/gyp/test/ios/copies-with-xcode-envvars/file2 new file mode 100644 index 00000000000000..af1b8ae35db461 --- /dev/null +++ b/tools/gyp/test/ios/copies-with-xcode-envvars/file2 @@ -0,0 +1 @@ +file2 contents diff --git a/tools/gyp/test/ios/copies-with-xcode-envvars/file3 b/tools/gyp/test/ios/copies-with-xcode-envvars/file3 new file mode 100644 index 00000000000000..43f16f35220657 --- /dev/null +++ b/tools/gyp/test/ios/copies-with-xcode-envvars/file3 @@ -0,0 +1 @@ +file3 contents diff --git a/tools/gyp/test/ios/copies-with-xcode-envvars/file4 b/tools/gyp/test/ios/copies-with-xcode-envvars/file4 new file mode 100644 index 00000000000000..5f7270a0847cc6 --- /dev/null +++ b/tools/gyp/test/ios/copies-with-xcode-envvars/file4 @@ -0,0 +1 @@ +file4 contents diff --git a/tools/gyp/test/ios/copies-with-xcode-envvars/file5 b/tools/gyp/test/ios/copies-with-xcode-envvars/file5 new file mode 100644 index 00000000000000..41f47186bd2197 --- /dev/null +++ b/tools/gyp/test/ios/copies-with-xcode-envvars/file5 @@ -0,0 +1 @@ +file5 contents diff --git a/tools/gyp/test/ios/copies-with-xcode-envvars/file6 b/tools/gyp/test/ios/copies-with-xcode-envvars/file6 new file mode 100644 index 00000000000000..f5d57573486772 --- /dev/null +++ b/tools/gyp/test/ios/copies-with-xcode-envvars/file6 @@ -0,0 +1 @@ +file6 contents diff --git a/tools/gyp/test/ios/copies-with-xcode-envvars/file7 b/tools/gyp/test/ios/copies-with-xcode-envvars/file7 new file mode 100644 index 00000000000000..90dbe6e9e1123b --- /dev/null +++ b/tools/gyp/test/ios/copies-with-xcode-envvars/file7 @@ -0,0 +1 @@ +file7 contents diff --git a/tools/gyp/test/ios/copies-with-xcode-envvars/file8 b/tools/gyp/test/ios/copies-with-xcode-envvars/file8 new file mode 100644 index 00000000000000..9eb613fabbf7ec --- /dev/null +++ b/tools/gyp/test/ios/copies-with-xcode-envvars/file8 @@ -0,0 +1 @@ +file8 contents diff --git a/tools/gyp/test/ios/copies-with-xcode-envvars/file9 b/tools/gyp/test/ios/copies-with-xcode-envvars/file9 new file mode 100644 index 00000000000000..e37ac72adab0db --- /dev/null +++ b/tools/gyp/test/ios/copies-with-xcode-envvars/file9 @@ -0,0 +1 @@ +file9 contents diff --git a/tools/gyp/test/ios/deployment-target/check-version-min.c b/tools/gyp/test/ios/deployment-target/check-version-min.c new file mode 100644 index 00000000000000..761c529085d52a --- /dev/null +++ b/tools/gyp/test/ios/deployment-target/check-version-min.c @@ -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. */ + +#include + +/* GYPTEST_MAC_VERSION_MIN: should be set to the corresponding value of + * xcode setting 'MACOSX_DEPLOYMENT_TARGET', otherwise both should be + * left undefined. + * + * GYPTEST_IOS_VERSION_MIN: should be set to the corresponding value of + * xcode setting 'IPHONEOS_DEPLOYMENT_TARGET', otherwise both should be + * left undefined. + */ + +#if defined(GYPTEST_MAC_VERSION_MIN) +# if GYPTEST_MAC_VERSION_MIN != __MAC_OS_X_VERSION_MIN_REQUIRED +# error __MAC_OS_X_VERSION_MIN_REQUIRED has wrong value +# endif +#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +# error __MAC_OS_X_VERSION_MIN_REQUIRED should be undefined +#endif + +#if defined(GYPTEST_IOS_VERSION_MIN) +# if GYPTEST_IOS_VERSION_MIN != __IPHONE_OS_VERSION_MIN_REQUIRED +# error __IPHONE_OS_VERSION_MIN_REQUIRED has wrong value +# endif +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +# error __IPHONE_OS_VERSION_MIN_REQUIRED should be undefined +#endif + +int main() { return 0; } + diff --git a/tools/gyp/test/ios/deployment-target/deployment-target.gyp b/tools/gyp/test/ios/deployment-target/deployment-target.gyp new file mode 100644 index 00000000000000..bdc1439b5ec096 --- /dev/null +++ b/tools/gyp/test/ios/deployment-target/deployment-target.gyp @@ -0,0 +1,34 @@ +# 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'], + ['CXX', '/usr/bin/clang++'], + ], + 'targets': [ + { + 'target_name': 'version-min-4.3', + 'type': 'static_library', + 'sources': [ 'check-version-min.c', ], + 'defines': [ 'GYPTEST_IOS_VERSION_MIN=40300', ], + 'xcode_settings': { + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + 'SDKROOT': 'iphoneos', + 'IPHONEOS_DEPLOYMENT_TARGET': '4.3', + }, + }, + { + 'target_name': 'version-min-5.0', + 'type': 'static_library', + 'sources': [ 'check-version-min.c', ], + 'defines': [ 'GYPTEST_IOS_VERSION_MIN=50000', ], + 'xcode_settings': { + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + 'SDKROOT': 'iphoneos', + 'IPHONEOS_DEPLOYMENT_TARGET': '5.0', + }, + } + ], +} + diff --git a/tools/gyp/test/ios/extension/ActionExtension/ActionViewController.h b/tools/gyp/test/ios/extension/ActionExtension/ActionViewController.h new file mode 100644 index 00000000000000..1c925090296183 --- /dev/null +++ b/tools/gyp/test/ios/extension/ActionExtension/ActionViewController.h @@ -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 --git a/tools/gyp/test/ios/extension/ActionExtension/ActionViewController.m b/tools/gyp/test/ios/extension/ActionExtension/ActionViewController.m new file mode 100644 index 00000000000000..d37bacdae1764c --- /dev/null +++ b/tools/gyp/test/ios/extension/ActionExtension/ActionViewController.m @@ -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 --git a/tools/gyp/test/ios/extension/ActionExtension/Info.plist b/tools/gyp/test/ios/extension/ActionExtension/Info.plist new file mode 100644 index 00000000000000..f89cd790bc23b1 --- /dev/null +++ b/tools/gyp/test/ios/extension/ActionExtension/Info.plist @@ -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 --git a/tools/gyp/test/ios/extension/ActionExtension/MainInterface.storyboard b/tools/gyp/test/ios/extension/ActionExtension/MainInterface.storyboard new file mode 100644 index 00000000000000..5aa58184e80bba --- /dev/null +++ b/tools/gyp/test/ios/extension/ActionExtension/MainInterface.storyboard @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/gyp/test/ios/extension/ExtensionContainer/AppDelegate.h b/tools/gyp/test/ios/extension/ExtensionContainer/AppDelegate.h new file mode 100644 index 00000000000000..510e2300b1c6e6 --- /dev/null +++ b/tools/gyp/test/ios/extension/ExtensionContainer/AppDelegate.h @@ -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 --git a/tools/gyp/test/ios/extension/ExtensionContainer/AppDelegate.m b/tools/gyp/test/ios/extension/ExtensionContainer/AppDelegate.m new file mode 100644 index 00000000000000..1197bc1bbc0ca7 --- /dev/null +++ b/tools/gyp/test/ios/extension/ExtensionContainer/AppDelegate.m @@ -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 --git a/tools/gyp/test/ios/extension/ExtensionContainer/Base.lproj/Main.storyboard b/tools/gyp/test/ios/extension/ExtensionContainer/Base.lproj/Main.storyboard new file mode 100644 index 00000000000000..e8f3cfb40c36f8 --- /dev/null +++ b/tools/gyp/test/ios/extension/ExtensionContainer/Base.lproj/Main.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/gyp/test/ios/extension/ExtensionContainer/Images.xcassets/AppIcon.appiconset/Contents.json b/tools/gyp/test/ios/extension/ExtensionContainer/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000000000..f697f61f4aaf5c --- /dev/null +++ b/tools/gyp/test/ios/extension/ExtensionContainer/Images.xcassets/AppIcon.appiconset/Contents.json @@ -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 --git a/tools/gyp/test/ios/extension/ExtensionContainer/Images.xcassets/LaunchImage.launchimage/Contents.json b/tools/gyp/test/ios/extension/ExtensionContainer/Images.xcassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 00000000000000..4458b40c055859 --- /dev/null +++ b/tools/gyp/test/ios/extension/ExtensionContainer/Images.xcassets/LaunchImage.launchimage/Contents.json @@ -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 --git a/tools/gyp/test/ios/extension/ExtensionContainer/Info.plist b/tools/gyp/test/ios/extension/ExtensionContainer/Info.plist new file mode 100644 index 00000000000000..31ccf4cc82e149 --- /dev/null +++ b/tools/gyp/test/ios/extension/ExtensionContainer/Info.plist @@ -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 --git a/tools/gyp/test/ios/extension/ExtensionContainer/ViewController.h b/tools/gyp/test/ios/extension/ExtensionContainer/ViewController.h new file mode 100644 index 00000000000000..fad7754714edc9 --- /dev/null +++ b/tools/gyp/test/ios/extension/ExtensionContainer/ViewController.h @@ -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 --git a/tools/gyp/test/ios/extension/ExtensionContainer/ViewController.m b/tools/gyp/test/ios/extension/ExtensionContainer/ViewController.m new file mode 100644 index 00000000000000..3810fa9cba82c2 --- /dev/null +++ b/tools/gyp/test/ios/extension/ExtensionContainer/ViewController.m @@ -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 --git a/tools/gyp/test/ios/extension/ExtensionContainer/main.m b/tools/gyp/test/ios/extension/ExtensionContainer/main.m new file mode 100644 index 00000000000000..47aecb514839c4 --- /dev/null +++ b/tools/gyp/test/ios/extension/ExtensionContainer/main.m @@ -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 --git a/tools/gyp/test/ios/extension/extension.gyp b/tools/gyp/test/ios/extension/extension.gyp new file mode 100644 index 00000000000000..91c068413d7ef1 --- /dev/null +++ b/tools/gyp/test/ios/extension/extension.gyp @@ -0,0 +1,91 @@ +# 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_SIGNING_REQUIRED': 'NO', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + 'CONFIGURATION_BUILD_DIR':'build/Default', + }, + }, + { + '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_SIGNING_REQUIRED': 'NO', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + 'CONFIGURATION_BUILD_DIR':'build/Default', + }, + }, + ], +} + diff --git a/tools/gyp/test/ios/framework/framework.gyp b/tools/gyp/test/ios/framework/framework.gyp new file mode 100644 index 00000000000000..2c6fdd5b272ac2 --- /dev/null +++ b/tools/gyp/test/ios/framework/framework.gyp @@ -0,0 +1,43 @@ +# Copyright 2016 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': 'iOSFramework', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ + 'iOSFramework/iOSFramework.h', + 'iOSFramework/Thing.h', + 'iOSFramework/Thing.m', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + '$(SDKROOT)/System/Library/Frameworks/UIKit.framework', + ], + }, + 'mac_framework_headers': [ + # Using two headers here tests mac_tool.py NextGreaterPowerOf2. + 'iOSFramework/iOSFramework.h', + 'iOSFramework/Thing.h', + ], + 'mac_framework_dirs': [ + '$(SDKROOT)/../../Library/Frameworks', + ], + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-fobjc-abi-version=2', + ], + 'INFOPLIST_FILE': 'iOSFramework/Info.plist', + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + 'SDKROOT': 'iphoneos', + 'IPHONEOS_DEPLOYMENT_TARGET': '8.0', + 'CONFIGURATION_BUILD_DIR':'build/Default', + 'CODE_SIGN_IDENTITY[sdk=iphoneos*]': 'iPhone Developer', + }, + }, + ], +} diff --git a/tools/gyp/test/ios/framework/iOSFramework/Info.plist b/tools/gyp/test/ios/framework/iOSFramework/Info.plist new file mode 100644 index 00000000000000..d3de8eefb69556 --- /dev/null +++ b/tools/gyp/test/ios/framework/iOSFramework/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/tools/gyp/test/ios/framework/iOSFramework/Thing.h b/tools/gyp/test/ios/framework/iOSFramework/Thing.h new file mode 100644 index 00000000000000..a34e908fc9134e --- /dev/null +++ b/tools/gyp/test/ios/framework/iOSFramework/Thing.h @@ -0,0 +1,10 @@ +#import +#import + +@interface Thing : NSObject + ++ (instancetype)thing; + +- (void)sayHello; + +@end diff --git a/tools/gyp/test/ios/framework/iOSFramework/Thing.m b/tools/gyp/test/ios/framework/iOSFramework/Thing.m new file mode 100644 index 00000000000000..5b2b54925e3246 --- /dev/null +++ b/tools/gyp/test/ios/framework/iOSFramework/Thing.m @@ -0,0 +1,22 @@ +#import "Thing.h" + +@interface Thing () + +@end + +@implementation Thing + ++ (instancetype)thing { + static Thing* thing = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + thing = [[[self class] alloc] init]; + }); + return thing; +} + +- (void)sayHello { + NSLog(@"Hello World"); +} + +@end diff --git a/tools/gyp/test/ios/framework/iOSFramework/iOSFramework.h b/tools/gyp/test/ios/framework/iOSFramework/iOSFramework.h new file mode 100644 index 00000000000000..e86b524d179f7f --- /dev/null +++ b/tools/gyp/test/ios/framework/iOSFramework/iOSFramework.h @@ -0,0 +1,9 @@ +#import + +//! Project version number for iOSFramework. +FOUNDATION_EXPORT double iOSFrameworkVersionNumber; + +//! Project version string for iOSFramework. +FOUNDATION_EXPORT const unsigned char iOSFrameworkVersionString[]; + +#import diff --git a/tools/gyp/test/ios/gyptest-app-ios-assets-catalog.py b/tools/gyp/test/ios/gyptest-app-ios-assets-catalog.py new file mode 100644 index 00000000000000..537adc0b3bce9f --- /dev/null +++ b/tools/gyp/test/ios/gyptest-app-ios-assets-catalog.py @@ -0,0 +1,37 @@ +""" +Verifies that ios app bundles are built correctly. +""" + +import os.path + +import TestGyp +from XCodeDetect import XCodeDetect + +test = TestGyp.TestGyp(formats=['xcode', 'ninja'], platforms=['darwin']) + +# Xcode supports for assets catalog was introduced in Xcode 6.0 +if XCodeDetect.Version() < '0600': + test.skip_test('Skip test on XCode < 0600') + +test_gyp_path = 'test-assets-catalog.gyp' +test_app_path = 'Test App Assets Catalog Gyp.app' +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 --git a/tools/gyp/test/ios/gyptest-app-ios.py b/tools/gyp/test/ios/gyptest-app-ios.py new file mode 100644 index 00000000000000..04944f4dfb8fa0 --- /dev/null +++ b/tools/gyp/test/ios/gyptest-app-ios.py @@ -0,0 +1,62 @@ +""" +Verifies that ios app bundles are built correctly. +""" + +import subprocess + +import TestGyp +import XCodeDetect + +test = TestGyp.TestGyp(formats=['xcode', 'ninja'], platforms=['darwin']) + +if not XCodeDetect.XCodeDetect.HasIPhoneSDK(): + test.skip_test('IPhone SDK not installed') + + +def CheckFileXMLPropertyList(file): + output = subprocess.check_output(['file', file]) + if not 'XML 1.0 document text' in output: + print('File: Expected XML 1.0 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() + + +test.run_gyp('test.gyp', chdir='app-bundle') + +test.build('test.gyp', test.ALL, chdir='app-bundle') + +# Test that the extension is .bundle +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.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) + +extra_plist_file = test.built_file_path('Test App Gyp.app/English.lproj/LanguageMap.plist', chdir='app-bundle') +test.built_file_must_exist(extra_plist_file) +CheckFileBinaryPropertyList(extra_plist_file) + +test.built_file_must_exist('Test App Gyp.app/English.lproj/MainMenu.nib', chdir='app-bundle') +test.built_file_must_exist('Test App Gyp.app/English.lproj/Main_iPhone.storyboardc', chdir='app-bundle') + +# Packaging +test.built_file_must_exist('Test App Gyp.app/PkgInfo', chdir='app-bundle') +test.built_file_must_match('Test App Gyp.app/PkgInfo', 'APPLause', chdir='app-bundle') + +test.pass_test() diff --git a/tools/gyp/test/ios/gyptest-archs.py b/tools/gyp/test/ios/gyptest-archs.py new file mode 100644 index 00000000000000..8c2f86a881e413 --- /dev/null +++ b/tools/gyp/test/ios/gyptest-archs.py @@ -0,0 +1,59 @@ +#!/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 collections + +import TestGyp +import XCodeDetect + +test = TestGyp.TestGyp(formats=['ninja', 'xcode'], platforms=['darwin']) + +if test.format == 'xcode': + # This test appears to hang flakily. + test.skip_test() # bug=532 + +test_cases = [ + ('Default', 'TestArch32Bits', ['i386']), + ('Default-iphoneos', 'TestArch32Bits', ['armv7']), +] + +if XCodeDetect.XCodeDetect.Version() < '0510': + test_cases.extend([ + ('Default', 'TestNoArchs', ['i386']), + ('Default-iphoneos', 'TestNoArchs', ['armv7'])]) + +if XCodeDetect.XCodeDetect.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 XCodeDetect.XCodeDetect.Version() < '0500': + kwds['arguments'].extend(['-arch', archs[0]]) + + test.set_configuration(configuration) + filename = '%s.app/%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) + TestGyp.CheckFileType_macOS(test, result_file, archs) + +test.pass_test() diff --git a/tools/gyp/test/ios/gyptest-copies-with-xcode-envvars.py b/tools/gyp/test/ios/gyptest-copies-with-xcode-envvars.py new file mode 100644 index 00000000000000..c7ae79d507df71 --- /dev/null +++ b/tools/gyp/test/ios/gyptest-copies-with-xcode-envvars.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python + +# Copyright (c) 2016 Mark Callow. 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 files are copied to the correct destinations when those +destinations are specified using environment variables available in +Xcode's PBXCopyFilesBuildPhase. +""" + +import TestGyp + +import os +import stat +import sys + + +test = TestGyp.TestGyp(formats=['ninja', 'xcode']) + +if sys.platform == 'darwin': + test.run_gyp('copies-with-xcode-envvars.gyp', + chdir='copies-with-xcode-envvars') + + test.build('copies-with-xcode-envvars.gyp', chdir='copies-with-xcode-envvars') + + wrapper_name = 'copies-with-xcode-envvars.app/' + contents_path = wrapper_name + out_path = test.built_file_path('file0', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file0 contents\n') + out_path = test.built_file_path(wrapper_name + 'file1', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file1 contents\n') + out_path = test.built_file_path(contents_path + 'file2', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file2 contents\n') + out_path = test.built_file_path(contents_path + 'file3', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file3 contents\n') + out_path = test.built_file_path(contents_path + 'testimages/file4', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file4 contents\n') + out_path = test.built_file_path(contents_path + 'Java/file5', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file5 contents\n') + out_path = test.built_file_path(contents_path + 'Frameworks/file6', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file6 contents\n') + out_path = test.built_file_path(contents_path + 'Frameworks/file7', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file7 contents\n') + out_path = test.built_file_path(contents_path + 'SharedFrameworks/file8', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file8 contents\n') + out_path = test.built_file_path(contents_path + 'SharedSupport/file9', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file9 contents\n') + out_path = test.built_file_path(contents_path + 'PlugIns/file10', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file10 contents\n') + out_path = test.built_file_path(contents_path + 'XPCServices/file11', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file11 contents\n') + test.pass_test() diff --git a/tools/gyp/test/ios/gyptest-crosscompile.py b/tools/gyp/test/ios/gyptest-crosscompile.py new file mode 100644 index 00000000000000..8975a92a0e4937 --- /dev/null +++ b/tools/gyp/test/ios/gyptest-crosscompile.py @@ -0,0 +1,18 @@ +""" +Verifies that tools are built correctly. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['ninja', 'xcode'], platforms=['darwin']) + +with TestGyp.LocalEnv({'GYP_CROSSCOMPILE': '1'}): + test.run_gyp('test-crosscompile.gyp', chdir='app-bundle') + +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) +TestGyp.CheckFileType_macOS(test, result_file, ['x86_64']) + +test.pass_test() diff --git a/tools/gyp/test/ios/gyptest-deployment-target.py b/tools/gyp/test/ios/gyptest-deployment-target.py new file mode 100644 index 00000000000000..0e652e47f3a0ef --- /dev/null +++ b/tools/gyp/test/ios/gyptest-deployment-target.py @@ -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. + +""" +Verifies that IPHONEOS_DEPLOYMENT_TARGET works. +""" + +import TestGyp +import XCodeDetect + +test = TestGyp.TestGyp(formats=['make', 'ninja', 'xcode'], platforms=['darwin']) + +if not XCodeDetect.XCodeDetect.HasIPhoneSDK(): + test.skip_test('IPhone SDK not installed') + +test.run_gyp('deployment-target.gyp', chdir='deployment-target') + +test.build('deployment-target.gyp', test.ALL, chdir='deployment-target') + +test.pass_test() + diff --git a/tools/gyp/test/ios/gyptest-extension.py b/tools/gyp/test/ios/gyptest-extension.py new file mode 100644 index 00000000000000..c03dd4a4bb5d72 --- /dev/null +++ b/tools/gyp/test/ios/gyptest-extension.py @@ -0,0 +1,52 @@ +#!/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. +""" + +from __future__ import print_function + +import subprocess + +import TestGyp +from XCodeDetect import XCodeDetect + +test = TestGyp.TestGyp(formats=['ninja', 'xcode'], platforms=['darwin']) + +if XCodeDetect.Version() < '0600': + test.skip_test('Skip test on XCode < 0600') + + +def CheckStrip(p, expected): + if expected not in subprocess.check_output(['nm', '-gU', p]): + print(expected + " shouldn't get stripped out.") + test.fail_test() + + +def CheckEntrypoint(p, expected): + if expected not in subprocess.check_output(['nm', p]): + print(expected + "not found.") + test.fail_test() + + +if test.format in ('ninja', 'xcode-ninja'): + test.skip_test() # bug=534 + +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') + +path = test.built_file_path('ExtensionContainer.app/PlugIns/ActionExtension.appex/ActionExtension', chdir='extension') +CheckStrip(path, "ActionViewController") +CheckEntrypoint(path, "_NSExtensionMain") + +test.pass_test() diff --git a/tools/gyp/test/ios/gyptest-framework.py b/tools/gyp/test/ios/gyptest-framework.py new file mode 100644 index 00000000000000..571163a62f7dd6 --- /dev/null +++ b/tools/gyp/test/ios/gyptest-framework.py @@ -0,0 +1,24 @@ +""" +Verifies that ios app frameworks are built correctly. +""" + +import TestGyp +from XCodeDetect import XCodeDetect + +test = TestGyp.TestGyp(formats=['ninja'], platforms=['darwin']) + +if XCodeDetect.Version() < '0700': + test.skip_test('Skip test on XCode < 0700') + +if test.format == 'xcode-ninja': + test.skip_test() + +test.run_gyp('framework.gyp', chdir='framework') + +test.build('framework.gyp', 'iOSFramework', chdir='framework') + +test.built_file_must_exist('iOSFramework.framework/Headers/iOSFramework.h', chdir='framework') +test.built_file_must_exist('iOSFramework.framework/Headers/Thing.h', chdir='framework') +test.built_file_must_exist('iOSFramework.framework/iOSFramework', chdir='framework') + +test.pass_test() diff --git a/tools/gyp/test/ios/gyptest-per-config-settings.py b/tools/gyp/test/ios/gyptest-per-config-settings.py new file mode 100644 index 00000000000000..c10d1f6ec0b54e --- /dev/null +++ b/tools/gyp/test/ios/gyptest-per-config-settings.py @@ -0,0 +1,185 @@ +#!/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. +""" + +from __future__ import print_function + +import os +import plistlib +import struct +import subprocess +import tempfile + +import TestGyp +from XCodeDetect import XCodeDetect + +test = TestGyp.TestGyp(formats=['ninja', 'xcode'], platforms=['darwin'], disable="This test is currently disabled: https://crbug.com/483696.") + + +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) + proc.wait() + 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 GetXcodeVersionValue(type): + args = ['xcodebuild', '-version', '-sdk', 'iphoneos', type] + job = subprocess.Popen(args, stdout=subprocess.PIPE) + return job.communicate()[0].strip() + + +def GetMachineBuild(): + args = ['sw_vers', '-buildVersion'] + 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): + subprocess.call(['plutil', '-convert', 'xml1', path], stdout=subprocess.PIPE) + + +test.run_gyp('test-device.gyp', chdir='app-bundle') + +test_configs = ['Default-iphoneos', 'Default'] +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.app/Test App Gyp', chdir='app-bundle') + test.must_exist(result_file) + info_plist = test.built_file_path('Test App Gyp.app/Info.plist', chdir='app-bundle') + plist = plistlib.readPlist(info_plist) + xcode_version = XCodeDetect.Version() + if xcode_version >= '0720': + if len(plist) != 23: + print('plist should have 23 entries, but it has %s' % len(plist)) + test.fail_test() + + # Values that will hopefully never change. + CheckPlistvalue(plist, 'CFBundleDevelopmentRegion', 'English') + CheckPlistvalue(plist, 'CFBundleExecutable', 'Test App Gyp') + CheckPlistvalue(plist, 'CFBundleIdentifier', 'com.google.Test App Gyp') + CheckPlistvalue(plist, 'CFBundleInfoDictionaryVersion', '6.0') + CheckPlistvalue(plist, 'CFBundleName', 'Test App Gyp') + CheckPlistvalue(plist, 'CFBundlePackageType', 'APPL') + CheckPlistvalue(plist, 'CFBundleShortVersionString', '1.0') + CheckPlistvalue(plist, 'CFBundleSignature', 'ause') + CheckPlistvalue(plist, 'CFBundleVersion', '1') + CheckPlistvalue(plist, 'NSMainNibFile', 'MainMenu') + CheckPlistvalue(plist, 'NSPrincipalClass', 'NSApplication') + CheckPlistvalue(plist, 'UIDeviceFamily', [1, 2]) + + # Values that get pulled from xcodebuild. + machine_build = GetMachineBuild() + platform_version = GetXcodeVersionValue('ProductVersion') + sdk_build = GetXcodeVersionValue('ProductBuildVersion') + + # Xcode keeps changing what gets included in executable plists, and it + # changes between device and simuator builds. Allow the strictest tests for + # Xcode 7.2 and above. + if xcode_version >= '0720': + CheckPlistvalue(plist, 'BuildMachineOSBuild', machine_build) + CheckPlistvalue(plist, 'DTCompiler', 'com.apple.compilers.llvm.clang.1_0') + CheckPlistvalue(plist, 'DTPlatformVersion', platform_version) + CheckPlistvalue(plist, 'DTSDKBuild', sdk_build) + CheckPlistvalue(plist, 'DTXcode', xcode_version) + CheckPlistvalue(plist, 'MinimumOSVersion', '8.0') + + if configuration == 'Default-iphoneos': + platform_name = 'iphoneos' + CheckFileType(result_file, 'armv7') + CheckPlistvalue(plist, 'CFBundleSupportedPlatforms', ['iPhoneOS']) + # Apple keeps changing their mind. + if xcode_version >= '0720': + CheckPlistvalue(plist, 'DTPlatformBuild', sdk_build) + else: + platform_name = 'iphonesimulator' + CheckFileType(result_file, 'i386') + CheckPlistvalue(plist, 'CFBundleSupportedPlatforms', ['iPhoneSimulator']) + if xcode_version >= '0720': + CheckPlistvalue(plist, 'DTPlatformBuild', '') + + CheckPlistvalue(plist, 'DTPlatformName', platform_name) + CheckPlistvalue(plist, 'DTSDKName', platform_name + platform_version) + + if HasCerts() and configuration == 'Default-iphoneos': + test.build('test-device.gyp', 'sig_test', chdir='app-bundle') + result_file = test.built_file_path('sigtest.app/sigtest', chdir='app-bundle') + CheckSignature(result_file) + info_plist = test.built_file_path('sigtest.app/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 --git a/tools/gyp/test/ios/gyptest-watch.py b/tools/gyp/test/ios/gyptest-watch.py new file mode 100644 index 00000000000000..93e4150b99c2e5 --- /dev/null +++ b/tools/gyp/test/ios/gyptest-watch.py @@ -0,0 +1,25 @@ +""" +Verifies that ios watch extensions and apps are built correctly. +""" + +from __future__ import print_function + +import TestGyp +from XCodeDetect import XCodeDetect + +test = TestGyp.TestGyp(formats=['ninja', 'xcode'], platforms=['darwin'], disable="This test is currently disabled: https://crbug.com/483696.") + +if XCodeDetect.Version() < '0620': + test.skip_test('Skip test on XCode < 0620') + +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 --git a/tools/gyp/test/ios/gyptest-xcode-ninja.py b/tools/gyp/test/ios/gyptest-xcode-ninja.py new file mode 100644 index 00000000000000..609db8c98f56f5 --- /dev/null +++ b/tools/gyp/test/ios/gyptest-xcode-ninja.py @@ -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 --git a/tools/gyp/test/ios/watch/WatchApp/Images.xcassets/AppIcon.appiconset/Contents.json b/tools/gyp/test/ios/watch/WatchApp/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000000000..562c5eff9792f1 --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchApp/Images.xcassets/AppIcon.appiconset/Contents.json @@ -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 --git a/tools/gyp/test/ios/watch/WatchApp/Images.xcassets/LaunchImage.launchimage/Contents.json b/tools/gyp/test/ios/watch/WatchApp/Images.xcassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 00000000000000..ed123feff6c4e1 --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchApp/Images.xcassets/LaunchImage.launchimage/Contents.json @@ -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 --git a/tools/gyp/test/ios/watch/WatchApp/Info.plist b/tools/gyp/test/ios/watch/WatchApp/Info.plist new file mode 100644 index 00000000000000..3cf65b82850160 --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchApp/Info.plist @@ -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 --git a/tools/gyp/test/ios/watch/WatchApp/Interface.storyboard b/tools/gyp/test/ios/watch/WatchApp/Interface.storyboard new file mode 100644 index 00000000000000..5f52cb6c9078db --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchApp/Interface.storyboard @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/tools/gyp/test/ios/watch/WatchContainer/AppDelegate.h b/tools/gyp/test/ios/watch/WatchContainer/AppDelegate.h new file mode 100644 index 00000000000000..510e2300b1c6e6 --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchContainer/AppDelegate.h @@ -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 --git a/tools/gyp/test/ios/watch/WatchContainer/AppDelegate.m b/tools/gyp/test/ios/watch/WatchContainer/AppDelegate.m new file mode 100644 index 00000000000000..1197bc1bbc0ca7 --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchContainer/AppDelegate.m @@ -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 --git a/tools/gyp/test/ios/watch/WatchContainer/Base.lproj/Main.storyboard b/tools/gyp/test/ios/watch/WatchContainer/Base.lproj/Main.storyboard new file mode 100644 index 00000000000000..e8f3cfb40c36f8 --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchContainer/Base.lproj/Main.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/gyp/test/ios/watch/WatchContainer/Images.xcassets/AppIcon.appiconset/Contents.json b/tools/gyp/test/ios/watch/WatchContainer/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000000000..f697f61f4aaf5c --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchContainer/Images.xcassets/AppIcon.appiconset/Contents.json @@ -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 --git a/tools/gyp/test/ios/watch/WatchContainer/Images.xcassets/LaunchImage.launchimage/Contents.json b/tools/gyp/test/ios/watch/WatchContainer/Images.xcassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 00000000000000..4458b40c055859 --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchContainer/Images.xcassets/LaunchImage.launchimage/Contents.json @@ -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 --git a/tools/gyp/test/ios/watch/WatchContainer/Info.plist b/tools/gyp/test/ios/watch/WatchContainer/Info.plist new file mode 100644 index 00000000000000..a40319c78eac09 --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchContainer/Info.plist @@ -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 --git a/tools/gyp/test/ios/watch/WatchContainer/ViewController.h b/tools/gyp/test/ios/watch/WatchContainer/ViewController.h new file mode 100644 index 00000000000000..fad7754714edc9 --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchContainer/ViewController.h @@ -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 --git a/tools/gyp/test/ios/watch/WatchContainer/ViewController.m b/tools/gyp/test/ios/watch/WatchContainer/ViewController.m new file mode 100644 index 00000000000000..3810fa9cba82c2 --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchContainer/ViewController.m @@ -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 --git a/tools/gyp/test/ios/watch/WatchContainer/main.m b/tools/gyp/test/ios/watch/WatchContainer/main.m new file mode 100644 index 00000000000000..47aecb514839c4 --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchContainer/main.m @@ -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 --git a/tools/gyp/test/ios/watch/WatchKitExtension/Images.xcassets/MyImage.imageset/Contents.json b/tools/gyp/test/ios/watch/WatchKitExtension/Images.xcassets/MyImage.imageset/Contents.json new file mode 100644 index 00000000000000..f80d9508688cad --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchKitExtension/Images.xcassets/MyImage.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/tools/gyp/test/ios/watch/WatchKitExtension/Info.plist b/tools/gyp/test/ios/watch/WatchKitExtension/Info.plist new file mode 100644 index 00000000000000..7a354643ef4ef2 --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchKitExtension/Info.plist @@ -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 --git a/tools/gyp/test/ios/watch/WatchKitExtension/InterfaceController.h b/tools/gyp/test/ios/watch/WatchKitExtension/InterfaceController.h new file mode 100644 index 00000000000000..c3395eb4845117 --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchKitExtension/InterfaceController.h @@ -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 --git a/tools/gyp/test/ios/watch/WatchKitExtension/InterfaceController.m b/tools/gyp/test/ios/watch/WatchKitExtension/InterfaceController.m new file mode 100644 index 00000000000000..564b7d1da55a31 --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchKitExtension/InterfaceController.m @@ -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 --git a/tools/gyp/test/ios/watch/WatchKitExtension/MainInterface.storyboard b/tools/gyp/test/ios/watch/WatchKitExtension/MainInterface.storyboard new file mode 100644 index 00000000000000..5aa58184e80bba --- /dev/null +++ b/tools/gyp/test/ios/watch/WatchKitExtension/MainInterface.storyboard @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/gyp/test/ios/watch/watch.gyp b/tools/gyp/test/ios/watch/watch.gyp new file mode 100644 index 00000000000000..49be5554eea92d --- /dev/null +++ b/tools/gyp/test/ios/watch/watch.gyp @@ -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 --git a/tools/gyp/test/ios/xctests/App/AppDelegate.h b/tools/gyp/test/ios/xctests/App/AppDelegate.h new file mode 100644 index 00000000000000..f8efce97edc573 --- /dev/null +++ b/tools/gyp/test/ios/xctests/App/AppDelegate.h @@ -0,0 +1,11 @@ +// Copyright 2015 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 + +@interface AppDelegate : UIResponder + +@property(strong, nonatomic) UIWindow* window; + +@end diff --git a/tools/gyp/test/ios/xctests/App/AppDelegate.m b/tools/gyp/test/ios/xctests/App/AppDelegate.m new file mode 100644 index 00000000000000..825dda75b75696 --- /dev/null +++ b/tools/gyp/test/ios/xctests/App/AppDelegate.m @@ -0,0 +1,18 @@ +// Copyright 2015 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 "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + +- (BOOL)application:(UIApplication*)application + didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { + return YES; +} + +@end diff --git a/tools/gyp/test/ios/xctests/App/Base.lproj/LaunchScreen.xib b/tools/gyp/test/ios/xctests/App/Base.lproj/LaunchScreen.xib new file mode 100644 index 00000000000000..063dc5ea79e6d8 --- /dev/null +++ b/tools/gyp/test/ios/xctests/App/Base.lproj/LaunchScreen.xib @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/gyp/test/ios/xctests/App/Base.lproj/Main.storyboard b/tools/gyp/test/ios/xctests/App/Base.lproj/Main.storyboard new file mode 100644 index 00000000000000..f56d2f3bb56e84 --- /dev/null +++ b/tools/gyp/test/ios/xctests/App/Base.lproj/Main.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/gyp/test/ios/xctests/App/Images.xcassets/AppIcon.appiconset/Contents.json b/tools/gyp/test/ios/xctests/App/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000000000..36d2c80d889317 --- /dev/null +++ b/tools/gyp/test/ios/xctests/App/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "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" + } +} \ No newline at end of file diff --git a/tools/gyp/test/ios/xctests/App/Info.plist b/tools/gyp/test/ios/xctests/App/Info.plist new file mode 100644 index 00000000000000..3f938f60f42b54 --- /dev/null +++ b/tools/gyp/test/ios/xctests/App/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.google.gyptest.App + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/tools/gyp/test/ios/xctests/App/ViewController.h b/tools/gyp/test/ios/xctests/App/ViewController.h new file mode 100644 index 00000000000000..95a281e8d8b6c0 --- /dev/null +++ b/tools/gyp/test/ios/xctests/App/ViewController.h @@ -0,0 +1,9 @@ +// Copyright 2015 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 + +@interface ViewController : UIViewController + +@end diff --git a/tools/gyp/test/ios/xctests/App/ViewController.m b/tools/gyp/test/ios/xctests/App/ViewController.m new file mode 100644 index 00000000000000..d38e3c5bb7a6b1 --- /dev/null +++ b/tools/gyp/test/ios/xctests/App/ViewController.m @@ -0,0 +1,21 @@ +// Copyright 2015 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 "ViewController.h" + +@interface ViewController () + +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; +} + +@end diff --git a/tools/gyp/test/ios/xctests/App/main.m b/tools/gyp/test/ios/xctests/App/main.m new file mode 100644 index 00000000000000..83368075cdb942 --- /dev/null +++ b/tools/gyp/test/ios/xctests/App/main.m @@ -0,0 +1,13 @@ +// Copyright 2015 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 +#import "AppDelegate.h" + +int main(int argc, char* argv[]) { + @autoreleasepool { + return UIApplicationMain( + argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/tools/gyp/test/ios/xctests/AppTests/AppTests.m b/tools/gyp/test/ios/xctests/AppTests/AppTests.m new file mode 100644 index 00000000000000..22121b089d5672 --- /dev/null +++ b/tools/gyp/test/ios/xctests/AppTests/AppTests.m @@ -0,0 +1,31 @@ +// Copyright 2015 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 +#import + +@interface AppTests : XCTestCase + +@end + +@implementation AppTests + +- (void)setUp { + [super setUp]; +} + +- (void)tearDown { + [super tearDown]; +} + +- (void)testExample { + XCTAssert(YES, @"Pass"); +} + +- (void)testPerformanceExample { + [self measureBlock:^{ + }]; +} + +@end diff --git a/tools/gyp/test/ios/xctests/AppTests/Info.plist b/tools/gyp/test/ios/xctests/AppTests/Info.plist new file mode 100644 index 00000000000000..d43ff4ba8d1ad9 --- /dev/null +++ b/tools/gyp/test/ios/xctests/AppTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.google.gyptest.AppTests + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/tools/gyp/test/ios/xctests/gyptest-xctests.py b/tools/gyp/test/ios/xctests/gyptest-xctests.py new file mode 100644 index 00000000000000..6642cfb938a96c --- /dev/null +++ b/tools/gyp/test/ios/xctests/gyptest-xctests.py @@ -0,0 +1,49 @@ +#!/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. + +""" +Verifies that iOS XCTests can be built correctly. +""" + +import TestGyp + +import os +import subprocess +import sys + +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() + +if sys.platform == "darwin": + # This test appears to be flaky and hangs some of the time. + sys.exit(2) # bug=531 + + test = TestGyp.TestGyp(formats=['xcode', 'ninja']) + test.run_gyp('xctests.gyp') + test_configs = ['Default'] + # TODO(crbug.com/557418): Enable this once xcodebuild works for iOS devices. + #if HasCerts() and test.format == 'xcode': + # test_configs.append('Default-iphoneos') + for config in test_configs: + test.set_configuration(config) + test.build('xctests.gyp', test.ALL) + test.built_file_must_exist('app_under_test.app/app_under_test') + test.built_file_must_exist('app_tests.xctest/app_tests') + if 'ninja' in test.format: + test.built_file_must_exist('obj/AppTests/app_tests.AppTests.i386.o') + test.built_file_must_exist('obj/AppTests/app_tests.AppTests.x86_64.o') + elif test.format == 'xcode': + xcode_object_path = os.path.join('..', 'xctests.build', + 'Default-iphonesimulator', + 'app_tests.build', 'Objects-normal', + '%s', 'AppTests.o') + test.built_file_must_exist(xcode_object_path % 'i386') + test.built_file_must_exist(xcode_object_path % 'x86_64') + test.pass_test() diff --git a/tools/gyp/test/ios/xctests/xctests.gyp b/tools/gyp/test/ios/xctests/xctests.gyp new file mode 100644 index 00000000000000..8d4d6393b77535 --- /dev/null +++ b/tools/gyp/test/ios/xctests/xctests.gyp @@ -0,0 +1,74 @@ +# Copyright 2015 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. +{ + 'conditions': [ + ['"<(GENERATOR)"=="ninja"', { + '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': 'iphonesimulator', # -isysroot + 'CONFIGURATION_BUILD_DIR':'build/Default', + 'IPHONEOS_DEPLOYMENT_TARGET': '9.0', + 'CODE_SIGN_IDENTITY[sdk=iphoneos*]': 'iPhone Developer', + } + }, + 'targets': [ + { + 'target_name': 'app_under_test', + 'type': 'executable', + 'mac_bundle': 1, + 'mac_bundle_resources': [ + 'App/Base.lproj/LaunchScreen.xib', + 'App/Base.lproj/Main.storyboard', + ], + 'sources': [ + 'App/AppDelegate.h', + 'App/AppDelegate.m', + 'App/ViewController.h', + 'App/ViewController.m', + 'App/main.m', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + '$(SDKROOT)/System/Library/Frameworks/UIKit.framework', + ], + }, + 'xcode_settings': { + 'INFOPLIST_FILE': 'App/Info.plist', + }, + }, + { + 'target_name': 'app_tests', + 'type': 'loadable_module', + 'mac_xctest_bundle': 1, + 'sources': [ + 'AppTests/AppTests.m', + ], + 'dependencies': [ + 'app_under_test' + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + ], + }, + 'xcode_settings': { + 'WRAPPER_EXTENSION': 'xctest', + 'INFOPLIST_FILE': 'AppTests/Info.plist', + 'BUNDLE_LOADER': '$(BUILT_PRODUCTS_DIR)/app_under_test.app/app_under_test', + 'TEST_HOST': '$(BUNDLE_LOADER)', + }, + }, + ], +} diff --git a/tools/gyp/test/library/gyptest-shared-obj-install-path.py b/tools/gyp/test/library/gyptest-shared-obj-install-path.py new file mode 100644 index 00000000000000..af335365f98e00 --- /dev/null +++ b/tools/gyp/test/library/gyptest-shared-obj-install-path.py @@ -0,0 +1,39 @@ +#!/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 .so files that are order only dependencies are specified by +their install location rather than by their alias. +""" + +# Python 2.5 needs this for the with statement. +from __future__ import with_statement + +import os +import TestGyp + +test = TestGyp.TestGyp(formats=['make']) + +test.run_gyp('shared_dependency.gyp', + chdir='src') +test.relocate('src', 'relocate/src') + +test.build('shared_dependency.gyp', test.ALL, chdir='relocate/src') + +makefile_path = 'relocate/src/Makefile' + +with open(makefile_path) as makefile: + make_contents = makefile.read() + +# If we remove the code to generate lib1, Make should still be able +# to build lib2 since lib1.so already exists. +make_contents = make_contents.replace('include lib1.target.mk', '') +with open(makefile_path, 'w') as makefile: + makefile.write(make_contents) + +test.build('shared_dependency.gyp', test.ALL, chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/library/gyptest-shared.py b/tools/gyp/test/library/gyptest-shared.py new file mode 100644 index 00000000000000..a1d2985d919bf1 --- /dev/null +++ b/tools/gyp/test/library/gyptest-shared.py @@ -0,0 +1,84 @@ +#!/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 simple build of a "Hello, world!" program with shared libraries, +including verifying that libraries are rebuilt correctly when functions +move between libraries. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('library.gyp', + '-Dlibrary=shared_library', + '-Dmoveable_function=lib1', + chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('library.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from program.c +Hello from lib1.c +Hello from lib2.c +Hello from lib1_moveable.c +""" +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + + +test.run_gyp('library.gyp', + '-Dlibrary=shared_library', + '-Dmoveable_function=lib2', + chdir='relocate/src') + +# Update program.c to force a rebuild. +test.sleep() +contents = test.read('relocate/src/program.c') +contents = contents.replace('Hello', 'Hello again') +test.write('relocate/src/program.c', contents) + +test.build('library.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello again from program.c +Hello from lib1.c +Hello from lib2.c +Hello from lib2_moveable.c +""" +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + + +test.run_gyp('library.gyp', + '-Dlibrary=shared_library', + '-Dmoveable_function=lib1', + chdir='relocate/src') + +# Update program.c to force a rebuild. +test.sleep() +contents = test.read('relocate/src/program.c') +contents = contents.replace('again', 'again again') +test.write('relocate/src/program.c', contents) + +# TODO(sgk): we have to force a rebuild of lib2 so that it weeds out +# the "moved" module. This should be done in gyp by adding a dependency +# on the generated .vcproj file itself. +test.touch('relocate/src/lib2.c') + +test.build('library.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello again again from program.c +Hello from lib1.c +Hello from lib2.c +Hello from lib1_moveable.c +""" +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + + +test.pass_test() diff --git a/tools/gyp/test/library/gyptest-static.py b/tools/gyp/test/library/gyptest-static.py new file mode 100644 index 00000000000000..4bc71c4962a169 --- /dev/null +++ b/tools/gyp/test/library/gyptest-static.py @@ -0,0 +1,84 @@ +#!/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 simple build of a "Hello, world!" program with static libraries, +including verifying that libraries are rebuilt correctly when functions +move between libraries. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('library.gyp', + '-Dlibrary=static_library', + '-Dmoveable_function=lib1', + chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('library.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from program.c +Hello from lib1.c +Hello from lib2.c +Hello from lib1_moveable.c +""" +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + + +test.run_gyp('library.gyp', + '-Dlibrary=static_library', + '-Dmoveable_function=lib2', + chdir='relocate/src') + +# Update program.c to force a rebuild. +test.sleep() +contents = test.read('relocate/src/program.c') +contents = contents.replace('Hello', 'Hello again') +test.write('relocate/src/program.c', contents) + +test.build('library.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello again from program.c +Hello from lib1.c +Hello from lib2.c +Hello from lib2_moveable.c +""" +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + + +test.run_gyp('library.gyp', + '-Dlibrary=static_library', + '-Dmoveable_function=lib1', + chdir='relocate/src') + +# Update program.c and lib2.c to force a rebuild. +test.sleep() +contents = test.read('relocate/src/program.c') +contents = contents.replace('again', 'again again') +test.write('relocate/src/program.c', contents) + +# TODO(sgk): we have to force a rebuild of lib2 so that it weeds out +# the "moved" module. This should be done in gyp by adding a dependency +# on the generated .vcproj file itself. +test.touch('relocate/src/lib2.c') + +test.build('library.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello again again from program.c +Hello from lib1.c +Hello from lib2.c +Hello from lib1_moveable.c +""" +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + + +test.pass_test() diff --git a/tools/gyp/test/library/src/lib1.c b/tools/gyp/test/library/src/lib1.c new file mode 100644 index 00000000000000..3866b1b845ff61 --- /dev/null +++ b/tools/gyp/test/library/src/lib1.c @@ -0,0 +1,10 @@ +#include + +#ifdef _WIN32 +__declspec(dllexport) +#endif +void lib1_function(void) +{ + fprintf(stdout, "Hello from lib1.c\n"); + fflush(stdout); +} diff --git a/tools/gyp/test/library/src/lib1_moveable.c b/tools/gyp/test/library/src/lib1_moveable.c new file mode 100644 index 00000000000000..5d3cc1d9aab267 --- /dev/null +++ b/tools/gyp/test/library/src/lib1_moveable.c @@ -0,0 +1,10 @@ +#include + +#ifdef _WIN32 +__declspec(dllexport) +#endif +void moveable_function(void) +{ + fprintf(stdout, "Hello from lib1_moveable.c\n"); + fflush(stdout); +} diff --git a/tools/gyp/test/library/src/lib2.c b/tools/gyp/test/library/src/lib2.c new file mode 100644 index 00000000000000..21dda726530fc2 --- /dev/null +++ b/tools/gyp/test/library/src/lib2.c @@ -0,0 +1,10 @@ +#include + +#ifdef _WIN32 +__declspec(dllexport) +#endif +void lib2_function(void) +{ + fprintf(stdout, "Hello from lib2.c\n"); + fflush(stdout); +} diff --git a/tools/gyp/test/library/src/lib2_moveable.c b/tools/gyp/test/library/src/lib2_moveable.c new file mode 100644 index 00000000000000..f645071d1eb863 --- /dev/null +++ b/tools/gyp/test/library/src/lib2_moveable.c @@ -0,0 +1,10 @@ +#include + +#ifdef _WIN32 +__declspec(dllexport) +#endif +void moveable_function(void) +{ + fprintf(stdout, "Hello from lib2_moveable.c\n"); + fflush(stdout); +} diff --git a/tools/gyp/test/library/src/library.gyp b/tools/gyp/test/library/src/library.gyp new file mode 100644 index 00000000000000..bc355164260373 --- /dev/null +++ b/tools/gyp/test/library/src/library.gyp @@ -0,0 +1,58 @@ +# 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. + +{ + 'variables': { + 'moveable_function%': 0, + }, + 'targets': [ + { + 'target_name': 'program', + 'type': 'executable', + 'dependencies': [ + 'lib1', + 'lib2', + ], + 'sources': [ + 'program.c', + ], + }, + { + 'target_name': 'lib1', + 'type': '<(library)', + 'sources': [ + 'lib1.c', + ], + 'conditions': [ + ['moveable_function=="lib1"', { + 'sources': [ + 'lib1_moveable.c', + ], + }], + ], + }, + { + 'target_name': 'lib2', + 'type': '<(library)', + 'sources': [ + 'lib2.c', + ], + 'conditions': [ + ['moveable_function=="lib2"', { + 'sources': [ + 'lib2_moveable.c', + ], + }], + ], + }, + ], + 'conditions': [ + ['OS=="linux"', { + 'target_defaults': { + # Support 64-bit shared libs (also works fine for 32-bit). + 'cflags': ['-fPIC'], + }, + }], + ], +} diff --git a/tools/gyp/test/library/src/program.c b/tools/gyp/test/library/src/program.c new file mode 100644 index 00000000000000..d460f60e40511f --- /dev/null +++ b/tools/gyp/test/library/src/program.c @@ -0,0 +1,15 @@ +#include + +extern void lib1_function(void); +extern void lib2_function(void); +extern void moveable_function(void); + +int main(void) +{ + fprintf(stdout, "Hello from program.c\n"); + fflush(stdout); + lib1_function(); + lib2_function(); + moveable_function(); + return 0; +} diff --git a/tools/gyp/test/library/src/shared_dependency.gyp b/tools/gyp/test/library/src/shared_dependency.gyp new file mode 100644 index 00000000000000..7d29f5de598551 --- /dev/null +++ b/tools/gyp/test/library/src/shared_dependency.gyp @@ -0,0 +1,33 @@ +# 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': 'lib1', + 'type': 'shared_library', + 'sources': [ + 'lib1.c', + ], + }, + { + 'target_name': 'lib2', + 'type': 'shared_library', + 'sources': [ + 'lib2.c', + ], + 'dependencies': [ + 'lib1', + ], + }, + ], + 'conditions': [ + ['OS=="linux"', { + 'target_defaults': { + # Support 64-bit shared libs (also works fine for 32-bit). + 'cflags': ['-fPIC'], + }, + }], + ], +} diff --git a/tools/gyp/test/library_dirs/gyptest-library-dirs.py b/tools/gyp/test/library_dirs/gyptest-library-dirs.py new file mode 100644 index 00000000000000..e725dd1176ead8 --- /dev/null +++ b/tools/gyp/test/library_dirs/gyptest-library-dirs.py @@ -0,0 +1,50 @@ +#!/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 library_dirs (in link_settings) are properly found. +""" + +import sys + +import TestGyp + +test = TestGyp.TestGyp() + +lib_dir = test.tempdir('secret_location') + +test.run_gyp('test.gyp', + '-D', 'abs_path_to_secret_library_location={0}'.format(lib_dir), + chdir='subdir') + +# Must build each target independently, since they are not in each others' +# 'dependencies' (test.ALL does NOT work here for some builders, and in any case +# would not ensure the correct ordering). +test.build('test.gyp', 'mylib', chdir='subdir') +test.build('test.gyp', 'libraries-search-path-test', chdir='subdir') + +expect = """Hello world +""" +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 --git a/tools/gyp/test/library_dirs/subdir/README.txt b/tools/gyp/test/library_dirs/subdir/README.txt new file mode 100644 index 00000000000000..4031ded85f6301 --- /dev/null +++ b/tools/gyp/test/library_dirs/subdir/README.txt @@ -0,0 +1 @@ +Make things live in a subdirectory, to make sure that DEPTH works correctly. diff --git a/tools/gyp/test/library_dirs/subdir/hello.cc b/tools/gyp/test/library_dirs/subdir/hello.cc new file mode 100644 index 00000000000000..5dbbd48d349c4e --- /dev/null +++ b/tools/gyp/test/library_dirs/subdir/hello.cc @@ -0,0 +1,11 @@ +// 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 "mylib.h" + +int main() { + std::cout << "Hello " << my_foo(99) << std::endl; + return 0; +} diff --git a/tools/gyp/test/library_dirs/subdir/mylib.cc b/tools/gyp/test/library_dirs/subdir/mylib.cc new file mode 100644 index 00000000000000..654f3d0e6cc8d2 --- /dev/null +++ b/tools/gyp/test/library_dirs/subdir/mylib.cc @@ -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. + +#include "mylib.h" + +std::string my_foo(int x) { + return std::string("world"); +} diff --git a/tools/gyp/test/library_dirs/subdir/mylib.h b/tools/gyp/test/library_dirs/subdir/mylib.h new file mode 100644 index 00000000000000..84b4022e7b180b --- /dev/null +++ b/tools/gyp/test/library_dirs/subdir/mylib.h @@ -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. + +#ifndef TEST_LIBRARY_DIRS_SUBDIR_MYLIB_H +#define TEST_LIBRARY_DIRS_SUBDIR_MYLIB_H + +#include + +std::string my_foo(int); + +#endif // TEST_LIBRARY_DIRS_SUBDIR_MYLIB_H diff --git a/tools/gyp/test/library_dirs/subdir/test-win.gyp b/tools/gyp/test/library_dirs/subdir/test-win.gyp new file mode 100644 index 00000000000000..033b6f7fdd03c6 --- /dev/null +++ b/tools/gyp/test/library_dirs/subdir/test-win.gyp @@ -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 --git a/tools/gyp/test/library_dirs/subdir/test.gyp b/tools/gyp/test/library_dirs/subdir/test.gyp new file mode 100644 index 00000000000000..f83d7f2bf1f8ff --- /dev/null +++ b/tools/gyp/test/library_dirs/subdir/test.gyp @@ -0,0 +1,68 @@ +# 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', + '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': { + 'conditions': [ + ['OS=="linux"', { + 'libraries': [ + '-lmylib', + ], + }, { # else + 'libraries': [ + '<(STATIC_LIB_PREFIX)mylib<(STATIC_LIB_SUFFIX)', + ], + }], + ], # conditions + }, + }, + ], +} diff --git a/tools/gyp/test/link-dependency/gyptest-link-dependency.py b/tools/gyp/test/link-dependency/gyptest-link-dependency.py new file mode 100644 index 00000000000000..3a8300d44e0031 --- /dev/null +++ b/tools/gyp/test/link-dependency/gyptest-link-dependency.py @@ -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 --git a/tools/gyp/test/link-dependency/main.c b/tools/gyp/test/link-dependency/main.c new file mode 100644 index 00000000000000..543d8b6951eecb --- /dev/null +++ b/tools/gyp/test/link-dependency/main.c @@ -0,0 +1,7 @@ +#include +#include +int main() { + void *p = malloc(1); + printf("p: %p\n", p); + return 0; +} diff --git a/tools/gyp/test/link-dependency/mymalloc.c b/tools/gyp/test/link-dependency/mymalloc.c new file mode 100644 index 00000000000000..f80bc02a62682e --- /dev/null +++ b/tools/gyp/test/link-dependency/mymalloc.c @@ -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 --git a/tools/gyp/test/link-dependency/test.gyp b/tools/gyp/test/link-dependency/test.gyp new file mode 100644 index 00000000000000..47cec15005f4c7 --- /dev/null +++ b/tools/gyp/test/link-dependency/test.gyp @@ -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 --git a/tools/gyp/test/link-objects/base.c b/tools/gyp/test/link-objects/base.c new file mode 100644 index 00000000000000..332745920522cd --- /dev/null +++ b/tools/gyp/test/link-objects/base.c @@ -0,0 +1,6 @@ +void extra(); + +int main(void) { + extra(); + return 0; +} diff --git a/tools/gyp/test/link-objects/extra.c b/tools/gyp/test/link-objects/extra.c new file mode 100644 index 00000000000000..1d7ee09b1079a6 --- /dev/null +++ b/tools/gyp/test/link-objects/extra.c @@ -0,0 +1,5 @@ +#include + +void extra() { + printf("PASS\n"); +} diff --git a/tools/gyp/test/link-objects/gyptest-all.py b/tools/gyp/test/link-objects/gyptest-all.py new file mode 100644 index 00000000000000..45bd6e1891357d --- /dev/null +++ b/tools/gyp/test/link-objects/gyptest-all.py @@ -0,0 +1,28 @@ +#!/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. + +""" +Put an object file on the sources list. +Expect the result to link ok. +""" + +import TestGyp + +import sys + +if sys.platform != 'darwin': + # Currently only works under the linux make build. + test = TestGyp.TestGyp(formats=['make']) + + test.run_gyp('link-objects.gyp') + + test.build('link-objects.gyp', test.ALL) + + test.run_built_executable('link-objects', stdout="PASS\n") + + test.up_to_date('link-objects.gyp', test.ALL) + + test.pass_test() diff --git a/tools/gyp/test/link-objects/link-objects.gyp b/tools/gyp/test/link-objects/link-objects.gyp new file mode 100644 index 00000000000000..ab72855531ae61 --- /dev/null +++ b/tools/gyp/test/link-objects/link-objects.gyp @@ -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': 'link-objects', + 'type': 'executable', + 'actions': [ + { + 'action_name': 'build extra object', + 'inputs': ['extra.c'], + 'outputs': ['extra.o'], + 'action': ['gcc', '-o', 'extra.o', '-c', 'extra.c'], + 'process_outputs_as_sources': 1, + }, + ], + 'sources': [ + 'base.c', + ], + }, + ], +} diff --git a/tools/gyp/test/linux/gyptest-implicit-rpath.py b/tools/gyp/test/linux/gyptest-implicit-rpath.py new file mode 100644 index 00000000000000..66361ef638e053 --- /dev/null +++ b/tools/gyp/test/linux/gyptest-implicit-rpath.py @@ -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 the implicit rpath is added only when needed. +""" + +import TestGyp + +import sys + +if sys.platform.startswith('linux'): + test = TestGyp.TestGyp(formats=['ninja', 'make']) + + CHDIR = 'implicit-rpath' + test.run_gyp('test.gyp', chdir=CHDIR) + test.build('test.gyp', test.ALL, chdir=CHDIR) + + expect = '$ORIGIN/lib/' if test.format == 'ninja' else '$ORIGIN/lib.target/' + + shared_executable = test.run_readelf('shared_executable', CHDIR) + if shared_executable != [expect]: + print('shared_executable=%s' % shared_executable) + print('expect=%s' % expect) + test.fail_test() + + shared_executable_no_so_suffix = test.run_readelf('shared_executable_no_so_suffix', CHDIR) + if shared_executable_no_so_suffix != [expect]: + test.fail_test() + + static_executable = test.run_readelf('static_executable', CHDIR) + if static_executable: + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/linux/gyptest-ldflags-duplicates.py b/tools/gyp/test/linux/gyptest-ldflags-duplicates.py new file mode 100644 index 00000000000000..43a4607adf9f7b --- /dev/null +++ b/tools/gyp/test/linux/gyptest-ldflags-duplicates.py @@ -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 --git a/tools/gyp/test/linux/gyptest-ldflags-from-environment.py b/tools/gyp/test/linux/gyptest-ldflags-from-environment.py new file mode 100644 index 00000000000000..55ef7afd91b315 --- /dev/null +++ b/tools/gyp/test/linux/gyptest-ldflags-from-environment.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +# Copyright (c) 2017 Google 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 the use of linker flags in environment variables. + +In this test, gyp and build both run in same local environment. +""" + +import TestGyp + +import re +import subprocess +import sys + +FORMATS = ('make', 'ninja') + +if sys.platform.startswith('linux'): + test = TestGyp.TestGyp(formats=FORMATS) + + CHDIR = 'ldflags-from-environment' + env = { + 'LDFLAGS': '-Wl,--dynamic-linker=/target', + 'LDFLAGS_host': '-Wl,--dynamic-linker=/host', + 'GYP_CROSSCOMPILE': '1' + } + with TestGyp.LocalEnv(env): + test.run_gyp('test.gyp', chdir=CHDIR) + test.build('test.gyp', chdir=CHDIR) + + ldflags = test.run_readelf('ldflags', CHDIR, '-l') + if ldflags != ['/target']: + test.fail_test() + + ldflags_host = test.run_readelf('ldflags_host', CHDIR, '-l') + if ldflags_host != ['/host']: + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/linux/gyptest-target-rpath.py b/tools/gyp/test/linux/gyptest-target-rpath.py new file mode 100644 index 00000000000000..8e3dffc71c83f0 --- /dev/null +++ b/tools/gyp/test/linux/gyptest-target-rpath.py @@ -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. + +""" +Check target_rpath generator flag for ninja. +""" + +import TestGyp + +import re +import subprocess +import sys + +if sys.platform.startswith('linux'): + test = TestGyp.TestGyp(formats=['ninja']) + + CHDIR = 'target-rpath' + test.run_gyp('test.gyp', '-G', 'target_rpath=/usr/lib/gyptest/', chdir=CHDIR) + test.build('test.gyp', test.ALL, chdir=CHDIR) + + expect = '/usr/lib/gyptest/' + + if test.run_readelf('shared_executable', chdir=CHDIR) != [expect]: + test.fail_test() + + if test.run_readelf('shared_executable_no_so_suffix', chdir=CHDIR) != [expect]: + test.fail_test() + + if test.run_readelf('static_executable', chdir=CHDIR): + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/linux/implicit-rpath/file.c b/tools/gyp/test/linux/implicit-rpath/file.c new file mode 100644 index 00000000000000..56757a701bf5cf --- /dev/null +++ b/tools/gyp/test/linux/implicit-rpath/file.c @@ -0,0 +1 @@ +void f() {} diff --git a/tools/gyp/test/linux/implicit-rpath/main.c b/tools/gyp/test/linux/implicit-rpath/main.c new file mode 100644 index 00000000000000..237c8ce181774d --- /dev/null +++ b/tools/gyp/test/linux/implicit-rpath/main.c @@ -0,0 +1 @@ +int main() {} diff --git a/tools/gyp/test/linux/implicit-rpath/test.gyp b/tools/gyp/test/linux/implicit-rpath/test.gyp new file mode 100644 index 00000000000000..b546106986e19d --- /dev/null +++ b/tools/gyp/test/linux/implicit-rpath/test.gyp @@ -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': 'shared', + 'type': 'shared_library', + 'sources': [ 'file.c' ], + }, + { + 'target_name': 'shared_no_so_suffix', + 'product_extension': 'so.0.1', + 'type': 'shared_library', + 'sources': [ 'file.c' ], + }, + { + 'target_name': 'static', + 'type': 'static_library', + 'sources': [ 'file.c' ], + }, + { + 'target_name': 'shared_executable', + 'type': 'executable', + 'sources': [ 'main.c' ], + 'dependencies': [ + 'shared', + ] + }, + { + 'target_name': 'shared_executable_no_so_suffix', + 'type': 'executable', + 'sources': [ 'main.c' ], + 'dependencies': [ + 'shared_no_so_suffix', + ] + }, + { + 'target_name': 'static_executable', + 'type': 'executable', + 'sources': [ 'main.c' ], + 'dependencies': [ + 'static', + ] + }, + ], +} diff --git a/tools/gyp/test/linux/ldflags-duplicates/check-ldflags.py b/tools/gyp/test/linux/ldflags-duplicates/check-ldflags.py new file mode 100644 index 00000000000000..ef1029529d510f --- /dev/null +++ b/tools/gyp/test/linux/ldflags-duplicates/check-ldflags.py @@ -0,0 +1,28 @@ +#!/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. +""" + +from __future__ import print_function + +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 --git a/tools/gyp/test/linux/ldflags-duplicates/lib1.c b/tools/gyp/test/linux/ldflags-duplicates/lib1.c new file mode 100644 index 00000000000000..a1322e73955c60 --- /dev/null +++ b/tools/gyp/test/linux/ldflags-duplicates/lib1.c @@ -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 --git a/tools/gyp/test/linux/ldflags-duplicates/lib2.c b/tools/gyp/test/linux/ldflags-duplicates/lib2.c new file mode 100644 index 00000000000000..8e7a082820674b --- /dev/null +++ b/tools/gyp/test/linux/ldflags-duplicates/lib2.c @@ -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 --git a/tools/gyp/test/linux/ldflags-duplicates/main.c b/tools/gyp/test/linux/ldflags-duplicates/main.c new file mode 100644 index 00000000000000..b3039ace96f3ce --- /dev/null +++ b/tools/gyp/test/linux/ldflags-duplicates/main.c @@ -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 --git a/tools/gyp/test/linux/ldflags-duplicates/test.gyp b/tools/gyp/test/linux/ldflags-duplicates/test.gyp new file mode 100644 index 00000000000000..c36835b18f0f77 --- /dev/null +++ b/tools/gyp/test/linux/ldflags-duplicates/test.gyp @@ -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 --git a/tools/gyp/test/linux/ldflags-from-environment/main.c b/tools/gyp/test/linux/ldflags-from-environment/main.c new file mode 100644 index 00000000000000..1b8742a1073654 --- /dev/null +++ b/tools/gyp/test/linux/ldflags-from-environment/main.c @@ -0,0 +1,7 @@ +// Copyright (c) 2017 Google 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 --git a/tools/gyp/test/linux/ldflags-from-environment/test.gyp b/tools/gyp/test/linux/ldflags-from-environment/test.gyp new file mode 100644 index 00000000000000..7ed1d07ed53ba4 --- /dev/null +++ b/tools/gyp/test/linux/ldflags-from-environment/test.gyp @@ -0,0 +1,23 @@ +# Copyright (c) 2017 Google 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': 'ldflags', + 'type': 'executable', + 'sources': [ + 'main.c', + ], + }, + { + 'target_name': 'ldflags_host', + 'toolsets': ['host'], + 'type': 'executable', + 'sources': [ + 'main.c', + ], + }, + ], +} diff --git a/tools/gyp/test/linux/target-rpath/file.c b/tools/gyp/test/linux/target-rpath/file.c new file mode 100644 index 00000000000000..56757a701bf5cf --- /dev/null +++ b/tools/gyp/test/linux/target-rpath/file.c @@ -0,0 +1 @@ +void f() {} diff --git a/tools/gyp/test/linux/target-rpath/main.c b/tools/gyp/test/linux/target-rpath/main.c new file mode 100644 index 00000000000000..237c8ce181774d --- /dev/null +++ b/tools/gyp/test/linux/target-rpath/main.c @@ -0,0 +1 @@ +int main() {} diff --git a/tools/gyp/test/linux/target-rpath/test.gyp b/tools/gyp/test/linux/target-rpath/test.gyp new file mode 100644 index 00000000000000..b546106986e19d --- /dev/null +++ b/tools/gyp/test/linux/target-rpath/test.gyp @@ -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': 'shared', + 'type': 'shared_library', + 'sources': [ 'file.c' ], + }, + { + 'target_name': 'shared_no_so_suffix', + 'product_extension': 'so.0.1', + 'type': 'shared_library', + 'sources': [ 'file.c' ], + }, + { + 'target_name': 'static', + 'type': 'static_library', + 'sources': [ 'file.c' ], + }, + { + 'target_name': 'shared_executable', + 'type': 'executable', + 'sources': [ 'main.c' ], + 'dependencies': [ + 'shared', + ] + }, + { + 'target_name': 'shared_executable_no_so_suffix', + 'type': 'executable', + 'sources': [ 'main.c' ], + 'dependencies': [ + 'shared_no_so_suffix', + ] + }, + { + 'target_name': 'static_executable', + 'type': 'executable', + 'sources': [ 'main.c' ], + 'dependencies': [ + 'static', + ] + }, + ], +} diff --git a/tools/gyp/test/mac/action-envvars/action/action.gyp b/tools/gyp/test/mac/action-envvars/action/action.gyp new file mode 100644 index 00000000000000..d9d65745ca3256 --- /dev/null +++ b/tools/gyp/test/mac/action-envvars/action/action.gyp @@ -0,0 +1,34 @@ +# 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': 'action', + 'type': 'none', + 'actions': [ + { + 'inputs': [ ], + 'outputs': [ + '<(PRODUCT_DIR)/result', + '<(SHARED_INTERMEDIATE_DIR)/tempfile', + ], + 'action_name': 'Test action', + 'action': ['./action.sh', '<(SHARED_INTERMEDIATE_DIR)/tempfile' ], + }, + { + 'inputs': [ + '<(SHARED_INTERMEDIATE_DIR)/tempfile', + ], + 'outputs': [ + '<(PRODUCT_DIR)/other_result', + ], + 'action_name': 'Other test action', + 'action': ['cp', '<(SHARED_INTERMEDIATE_DIR)/tempfile', + '<(PRODUCT_DIR)/other_result' ], + }, + ], + }, + ], +} + diff --git a/tools/gyp/test/mac/action-envvars/action/action.sh b/tools/gyp/test/mac/action-envvars/action/action.sh new file mode 100644 index 00000000000000..48d5f6bf86454f --- /dev/null +++ b/tools/gyp/test/mac/action-envvars/action/action.sh @@ -0,0 +1,8 @@ +# 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. + +set -e + +echo 'Test output' > "${BUILT_PRODUCTS_DIR}/result" +echo 'Other output' > "$1" diff --git a/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/InfoPlist-error.strings b/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/InfoPlist-error.strings new file mode 100644 index 00000000000000..452e7fabf9dc84 --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/InfoPlist-error.strings @@ -0,0 +1,3 @@ +/* Localized versions of Info.plist keys */ + +NSHumanReadableCopyright = "Copyright ©2011 Google Inc." diff --git a/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/InfoPlist.strings b/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/InfoPlist.strings new file mode 100644 index 00000000000000..35bd33a96e6a30 --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/InfoPlist.strings @@ -0,0 +1,3 @@ +/* Localized versions of Info.plist keys */ + +NSHumanReadableCopyright = "Copyright ©2011 Google Inc."; diff --git a/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/MainMenu.xib b/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/MainMenu.xib new file mode 100644 index 00000000000000..4524596787a8bd --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/MainMenu.xib @@ -0,0 +1,4119 @@ + + + + 1060 + 10A324 + 719 + 1015 + 418.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 719 + + + YES + + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + YES + + + TestApp + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + TestApp + + YES + + + About TestApp + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide TestApp + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit TestApp + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + Save As… + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + YES + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + Show Spelling and Grammar + : + 1048576 + 2147483647 + + + + + + Check Document Now + ; + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + Correct Spelling Automatically + + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Show Substitutions + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Dashes + + 2147483647 + + + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + Text Replacement + + 2147483647 + + + + + + + + + Transformations + + 2147483647 + + + submenuAction: + + Transformations + + YES + + + Make Upper Case + + 2147483647 + + + + + + Make Lower Case + + 2147483647 + + + + + + Capitalize + + 2147483647 + + + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + Format + + YES + + + Font + + 2147483647 + + + submenuAction: + + Font + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + Kern + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligature + + 2147483647 + + + submenuAction: + + Ligature + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + Baseline + + YES + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + Text + + YES + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Writing Direction + + 2147483647 + + + submenuAction: + + Writing Direction + + YES + + + YES + Paragraph + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + YES + Selection + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + YES + + + TestApp Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + 15 + 2 + {{335, 390}, {480, 360}} + 1954021376 + TestApp + NSWindow + + {1.79769e+308, 1.79769e+308} + + + 256 + {480, 360} + + + {{0, 0}, {1920, 1178}} + {1.79769e+308, 1.79769e+308} + + + TestAppAppDelegate + + + NSFontManager + + + + + YES + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + unhideAllApplications: + + + + 370 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + addFontTrait: + + + + 421 + + + + addFontTrait: + + + + 422 + + + + modifyFont: + + + + 423 + + + + orderFrontFontPanel: + + + + 424 + + + + modifyFont: + + + + 425 + + + + raiseBaseline: + + + + 426 + + + + lowerBaseline: + + + + 427 + + + + copyFont: + + + + 428 + + + + subscript: + + + + 429 + + + + superscript: + + + + 430 + + + + tightenKerning: + + + + 431 + + + + underline: + + + + 432 + + + + orderFrontColorPanel: + + + + 433 + + + + useAllLigatures: + + + + 434 + + + + loosenKerning: + + + + 435 + + + + pasteFont: + + + + 436 + + + + unscript: + + + + 437 + + + + useStandardKerning: + + + + 438 + + + + useStandardLigatures: + + + + 439 + + + + turnOffLigatures: + + + + 440 + + + + turnOffKerning: + + + + 441 + + + + terminate: + + + + 449 + + + + toggleAutomaticSpellingCorrection: + + + + 456 + + + + orderFrontSubstitutionsPanel: + + + + 458 + + + + toggleAutomaticDashSubstitution: + + + + 461 + + + + toggleAutomaticTextReplacement: + + + + 463 + + + + uppercaseWord: + + + + 464 + + + + capitalizeWord: + + + + 467 + + + + lowercaseWord: + + + + 468 + + + + pasteAsPlainText: + + + + 486 + + + + performFindPanelAction: + + + + 487 + + + + performFindPanelAction: + + + + 488 + + + + performFindPanelAction: + + + + 489 + + + + showHelp: + + + + 493 + + + + delegate + + + + 495 + + + + alignCenter: + + + + 518 + + + + pasteRuler: + + + + 519 + + + + toggleRuler: + + + + 520 + + + + alignRight: + + + + 521 + + + + copyRuler: + + + + 522 + + + + alignJustified: + + + + 523 + + + + alignLeft: + + + + 524 + + + + makeBaseWritingDirectionNatural: + + + + 525 + + + + makeBaseWritingDirectionLeftToRight: + + + + 526 + + + + makeBaseWritingDirectionRightToLeft: + + + + 527 + + + + makeTextWritingDirectionNatural: + + + + 528 + + + + makeTextWritingDirectionLeftToRight: + + + + 529 + + + + makeTextWritingDirectionRightToLeft: + + + + 530 + + + + window + + + + 532 + + + + + YES + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + 75 + + + + + 80 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + YES + + + + + + 77 + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 74 + + + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + 297 + + + + + 298 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 371 + + + YES + + + + + + 372 + + + + + 375 + + + YES + + + + + + 376 + + + YES + + + + + + + 377 + + + YES + + + + + + 388 + + + YES + + + + + + + + + + + + + + + + + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + + + 396 + + + + + 397 + + + YES + + + + + + 398 + + + YES + + + + + + 399 + + + YES + + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + + + 404 + + + + + 405 + + + YES + + + + + + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + + + 410 + + + + + 411 + + + YES + + + + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 415 + + + YES + + + + + + + + + 416 + + + + + 417 + + + + + 418 + + + + + 419 + + + + + 420 + + + + + 450 + + + YES + + + + + + 451 + + + YES + + + + + + + + 452 + + + + + 453 + + + + + 454 + + + + + 457 + + + + + 459 + + + + + 460 + + + + + 462 + + + + + 465 + + + + + 466 + + + + + 485 + + + + + 490 + + + YES + + + + + + 491 + + + YES + + + + + + 492 + + + + + 494 + + + + + 496 + + + YES + + + + + + 497 + + + YES + + + + + + + + + + + + + + + 498 + + + + + 499 + + + + + 500 + + + + + 501 + + + + + 502 + + + + + 503 + + + YES + + + + + + 504 + + + + + 505 + + + + + 506 + + + + + 507 + + + + + 508 + + + YES + + + + + + + + + + + + + + 509 + + + + + 510 + + + + + 511 + + + + + 512 + + + + + 513 + + + + + 514 + + + + + 515 + + + + + 516 + + + + + 517 + + + + + + + YES + + YES + -3.IBPluginDependency + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 195.IBPluginDependency + 195.ImportedFromIB2 + 196.IBPluginDependency + 196.ImportedFromIB2 + 197.IBPluginDependency + 197.ImportedFromIB2 + 198.IBPluginDependency + 198.ImportedFromIB2 + 199.IBPluginDependency + 199.ImportedFromIB2 + 200.IBEditorWindowLastContentRect + 200.IBPluginDependency + 200.ImportedFromIB2 + 200.editorWindowContentRectSynchronizationRect + 201.IBPluginDependency + 201.ImportedFromIB2 + 202.IBPluginDependency + 202.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 204.IBPluginDependency + 204.ImportedFromIB2 + 205.IBEditorWindowLastContentRect + 205.IBPluginDependency + 205.ImportedFromIB2 + 205.editorWindowContentRectSynchronizationRect + 206.IBPluginDependency + 206.ImportedFromIB2 + 207.IBPluginDependency + 207.ImportedFromIB2 + 208.IBPluginDependency + 208.ImportedFromIB2 + 209.IBPluginDependency + 209.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 211.IBPluginDependency + 211.ImportedFromIB2 + 212.IBPluginDependency + 212.ImportedFromIB2 + 212.editorWindowContentRectSynchronizationRect + 213.IBPluginDependency + 213.ImportedFromIB2 + 214.IBPluginDependency + 214.ImportedFromIB2 + 215.IBPluginDependency + 215.ImportedFromIB2 + 216.IBPluginDependency + 216.ImportedFromIB2 + 217.IBPluginDependency + 217.ImportedFromIB2 + 218.IBPluginDependency + 218.ImportedFromIB2 + 219.IBPluginDependency + 219.ImportedFromIB2 + 220.IBEditorWindowLastContentRect + 220.IBPluginDependency + 220.ImportedFromIB2 + 220.editorWindowContentRectSynchronizationRect + 221.IBPluginDependency + 221.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBEditorWindowLastContentRect + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBEditorWindowLastContentRect + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 297.IBPluginDependency + 298.IBPluginDependency + 346.IBPluginDependency + 346.ImportedFromIB2 + 348.IBPluginDependency + 348.ImportedFromIB2 + 349.IBEditorWindowLastContentRect + 349.IBPluginDependency + 349.ImportedFromIB2 + 349.editorWindowContentRectSynchronizationRect + 350.IBPluginDependency + 350.ImportedFromIB2 + 351.IBPluginDependency + 351.ImportedFromIB2 + 354.IBPluginDependency + 354.ImportedFromIB2 + 371.IBEditorWindowLastContentRect + 371.IBPluginDependency + 371.IBWindowTemplateEditedContentRect + 371.NSWindowTemplate.visibleAtLaunch + 371.editorWindowContentRectSynchronizationRect + 371.windowTemplate.maxSize + 372.IBPluginDependency + 375.IBPluginDependency + 376.IBEditorWindowLastContentRect + 376.IBPluginDependency + 377.IBPluginDependency + 388.IBEditorWindowLastContentRect + 388.IBPluginDependency + 389.IBPluginDependency + 390.IBPluginDependency + 391.IBPluginDependency + 392.IBPluginDependency + 393.IBPluginDependency + 394.IBPluginDependency + 395.IBPluginDependency + 396.IBPluginDependency + 397.IBPluginDependency + 398.IBPluginDependency + 399.IBPluginDependency + 400.IBPluginDependency + 401.IBPluginDependency + 402.IBPluginDependency + 403.IBPluginDependency + 404.IBPluginDependency + 405.IBPluginDependency + 406.IBPluginDependency + 407.IBPluginDependency + 408.IBPluginDependency + 409.IBPluginDependency + 410.IBPluginDependency + 411.IBPluginDependency + 412.IBPluginDependency + 413.IBPluginDependency + 414.IBPluginDependency + 415.IBPluginDependency + 416.IBPluginDependency + 417.IBPluginDependency + 418.IBPluginDependency + 419.IBPluginDependency + 450.IBPluginDependency + 451.IBEditorWindowLastContentRect + 451.IBPluginDependency + 452.IBPluginDependency + 453.IBPluginDependency + 454.IBPluginDependency + 457.IBPluginDependency + 459.IBPluginDependency + 460.IBPluginDependency + 462.IBPluginDependency + 465.IBPluginDependency + 466.IBPluginDependency + 485.IBPluginDependency + 490.IBPluginDependency + 491.IBEditorWindowLastContentRect + 491.IBPluginDependency + 492.IBPluginDependency + 496.IBPluginDependency + 497.IBEditorWindowLastContentRect + 497.IBPluginDependency + 498.IBPluginDependency + 499.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 500.IBPluginDependency + 501.IBPluginDependency + 502.IBPluginDependency + 503.IBPluginDependency + 504.IBPluginDependency + 505.IBPluginDependency + 506.IBPluginDependency + 507.IBPluginDependency + 508.IBEditorWindowLastContentRect + 508.IBPluginDependency + 509.IBPluginDependency + 510.IBPluginDependency + 511.IBPluginDependency + 512.IBPluginDependency + 513.IBPluginDependency + 514.IBPluginDependency + 515.IBPluginDependency + 516.IBPluginDependency + 517.IBPluginDependency + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 72.IBPluginDependency + 72.ImportedFromIB2 + 73.IBPluginDependency + 73.ImportedFromIB2 + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 78.IBPluginDependency + 78.ImportedFromIB2 + 79.IBPluginDependency + 79.ImportedFromIB2 + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{753, 187}, {275, 113}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{547, 180}, {254, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{187, 434}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {167, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{753, 217}, {238, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{654, 239}, {194, 73}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{525, 802}, {197, 73}} + {{380, 836}, {512, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{6, 978}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + {{604, 269}, {231, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + {{475, 832}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{746, 287}, {220, 133}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{380, 496}, {480, 360}} + com.apple.InterfaceBuilder.CocoaPlugin + {{380, 496}, {480, 360}} + + {{33, 99}, {480, 360}} + {3.40282e+38, 3.40282e+38} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{591, 420}, {83, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{523, 2}, {178, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{753, 197}, {170, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{725, 289}, {246, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{674, 260}, {204, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{878, 180}, {164, 173}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + {{286, 129}, {275, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{452, 109}, {196, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{145, 474}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + + YES + + + + + YES + + + YES + + + + 532 + + + + YES + + TestAppAppDelegate + NSObject + + window + NSWindow + + + IBProjectSource + TestAppAppDelegate.h + + + + + YES + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSUserInterfaceItemSearching.h + + + + NSBrowser + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSBrowser.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSDocument + NSObject + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + id + id + id + id + id + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocument.h + + + + NSDocument + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentScripting.h + + + + NSDocumentController + NSObject + + YES + + YES + clearRecentDocuments: + newDocument: + openDocument: + saveAllDocuments: + + + YES + id + id + id + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentController.h + + + + NSFontManager + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSMatrix + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSMatrix.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSMenuItem + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSMovieView + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMovieView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDictionaryController.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObjectScripting.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPortCoder.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptObjectSpecifiers.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptWhoseTests.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLDownload.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSTableView + NSControl + + + + NSText + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSText.h + + + + NSTextView + NSText + + IBFrameworkSource + AppKit.framework/Headers/NSTextView.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSDrawer.h + + + + NSWindow + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSWindowScripting.h + + + + + 0 + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + ../TestApp.xcodeproj + 3 + + diff --git a/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/utf-16be.strings b/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/utf-16be.strings new file mode 100644 index 0000000000000000000000000000000000000000..580783735f59601d6ac9d39cc2c3b21c66162e4a GIT binary patch literal 208 zcmZvW%?`m}5Jk_rPtkPQg}<#>Ss)P$o}j8l=ucWCypfm0QCpehoB8hCdor&#ePTkE zRHP)FIr1Q5r*^Y9v?>*)J+$Y(3xBzDkGk`>TvSiG@0}}_8CWYe%(+s?Em^xyJC)Nb~MR;8k}2lm`^;Vbvvr|$eM7uA#Qd*_OX=~*i_%(+s?Em=EHX+uL$Nkc;* zP;zf(X>4Tx07wm;mUmQB*%pV-y*Itk5+Wca^cs2zAksTX6$DXM^`x7XQc?|s+0 z08spb1j2M!0f022SQPH-!CVp(%f$Br7!UytSOLJ{W@ZFO_(THK{JlMynW#v{v-a*T zfMmPdEWc1DbJqWVks>!kBnAKqMb$PuekK>?0+ds;#ThdH1j_W4DKdsJG8Ul;qO2n0 z#IJ1jr{*iW$(WZWsE0n`c;fQ!l&-AnmjxZO1uWyz`0VP>&nP`#itsL#`S=Q!g`M=rU9)45( zJ;-|dRq-b5&z?byo>|{)?5r=n76A4nTALlSzLiw~v~31J<>9PP?;rs31pu_(obw)r zY+jPY;tVGXi|p)da{-@gE-UCa`=5eu%D;v=_nFJ?`&K)q7e9d`Nfk3?MdhZarb|T3 z%nS~f&t(1g5dY)AIcd$w!z`Siz!&j_=v7hZlnI21XuE|xfmo0(WD10T)!}~_HYW!e zew}L+XmwuzeT6wtxJd`dZ#@7*BLgIEKY9Xv>st^p3dp{^Xswa2bB{85{^$B13tWnB z;Y>jyQ|9&zk7RNsqAVGs--K+z0uqo1bf5|}fi5rtEMN^BfHQCd-XH*kfJhJnmIE$G z0%<@5vOzxB0181d*a3EfYH$G5fqKvcPJ%XY23!PJzzuK<41h;K3WmW;Fah3yX$XSw z5EY_9s*o0>51B&N5F1(uc|$=^I1~fLLy3?Ol0f;;Ca4%HgQ}rJP(Ab`bQ-z{U4#0d z2hboi2K@njgb|nm(_szR0JebHusa+GN5aeCM0gdP2N%HG;Yzp`J`T6S7vUT504#-H z!jlL<$Or?`Mpy_N@kBz9SR?@vA#0H$qyni$nvf2p8@Y{0k#Xb$28W?xm>3qu8RLgp zjNxKdVb)?wFx8l2m{v>|<~C*!GlBVnrDD~wrdTJeKXwT=5u1%I#8zOBU|X=4u>;s) z>^mF|$G{ol9B_WP7+f-LHLe7=57&&lfa}8z;U@8Tyei%l?}87(bMRt(A-)QK9Dg3) zj~~XrCy)tR1Z#p1A(kK{Y$Q|=8VKhI{e%(1G*N-5Pjn)N5P8I0VkxnX*g?EW941ba z6iJ387g8iCnY4jaNopcpCOsy-A(P2EWJhusSwLP-t|XrzUnLKcKTwn?CKOLf97RIe zPB}`sKzTrUL#0v;sBY9)s+hW+T2H-1eM)^VN0T#`^Oxhvt&^*fYnAJldnHel*Ozyf zUoM{~Um<@={-*r60#U(0!Bc^wuvVc);k3d%g-J!4qLpHZVwz%!VuRu}#Ze`^l7W)9 z5>Kf>>9Eozr6C$Z)1`URxU@~QI@)F0FdauXr2Es8>BaOP=)Lp_WhG@>R;lZ?BJkMlIuMhw8ApiF&yDYW2hFJ?fJhni{?u z85&g@mo&yT8JcdI$(rSw=QPK(Xj%)k1X|@<=e1rim6`6$RAwc!i#egKuI;BS(LSWz zt39n_sIypSqfWEV6J3%nTQ@-4i zi$R;gsG*9XzhRzXqv2yCs*$VFDx+GXJH|L;wsDH_KI2;^u!)^Xl1YupO;gy^-c(?^ z&$Q1BYvyPsG^;hc$D**@Sy`+`)}T4VJji^bd7Jqw3q6Zii=7tT7GEswEK@D(EFW1Z zSp`^awCb?>!`j4}Yh7b~$A)U-W3$et-R8BesV(1jzwLcHnq9En7Q0Tn&-M=XBKs!$ zF$X<|c!#|X_tWYh)GZit z(Q)Cp9CDE^WG;+fcyOWARoj*0TI>4EP1lX*cEoMO-Pk?Z{kZ!p4@(b`M~lalr<3Oz z&kJ6Nm#vN_+kA5{dW4@^Vjg_`q%qU1ULk& z3Fr!>1V#i_2R;ij2@(Z$1jE4r!MlPVFVbHmT+|iPIq0wy5aS{>yK?9ZAjVh%SOwMWgFjair&;wpi!{CU}&@N=Eg#~ zLQ&zpEzVmGY{hI9Z0+4-0xS$$Xe-OToc?Y*V;rTcf_ zb_jRe-RZjXSeas3UfIyD;9afd%<`i0x4T#DzE)vdabOQ=k7SRuGN`h>O0Q~1)u-yD z>VX=Mn&!Rgd$;YK+Q-}1zu#?t(*cbG#Ronf6db&N$oEidtwC+YVcg-Y!_VuY>bk#Y ze_ww@?MU&F&qswvrN_dLb=5o6*Egs)ls3YRlE$&)amR1{;Ppd$6RYV^Go!iq1UMl% z@#4q$AMc(FJlT1QeX8jv{h#)>&{~RGq1N2iiMFIRX?sk2-|2wUogK~{EkB$8eDsX= znVPf8XG_nK&J~=SIiGia@9y}|z3FhX{g&gcj=lwb=lWgyFW&aLedUh- zof`v-2Kw$UzI*>(+&$@i-u=-BsSjR1%z8NeX#HdC`Hh-Z(6xI-`hmHDqv!v)W&&nrf>M(RhcN6(D;jNN*%^u_SYjF;2ng}*8Ow)d6M ztDk;%`@Lsk$;9w$(d(H%O5UixIr`T2ZRcd@1`!T+Ex66Gv0|`DD_RX93e)DGL?Gqr$&sO&c%f7>^5Ey0KRz*tuAm5S< zS~I2D?1o^NVWmDnh+SKSDE*|YMS*|BYG)?!e=y#G5@MD`YM$ph$?Y>y7&Bm#Lv1s} z^Uo3LI%i^8`a2W2c3}q!qoOao=!TeIaIx(4ncEX)8ULC)mhp*nAFLV1o@oT=y0JU6Ux>sK@8%8rxdN#Dhy|?C0lAB#iLx zjfa_Xa-qpW_p3QFIXEGTa}C^E_3^tE2bczq9!q0sGSwvvXnG)JHcaE`iib%8&zF5P z;^2{-jq{pEQQu+4!qW5*IA-mIgUcTzmdhUAHw`SFj9+UYvt+8zF!nf@AHu2KT-*W^ zW8EU}z1jrEUv-8~fM@Fw&gE!7D&(n)8BFy?xdB!+WuwjT;S(2+zk~>SL8LdU0d6gL zs0`SXsW^VU{$2k+lbbDYXs3WnYTA!b(PYLz?u~rp5{)x7)Y6iuY^qCD5l}L?(-OL- xSlph87|b%bZF8rkbRWg-d|M!n;aFxc>o1aGziX+uL$Nkc;* zP;zf(X>4Tx07wm;mUmQB*%pV-y*Itk5+Wca^cs2zAksTX6$DXM^`x7XQc?|s+0 z08spb1j2M!0f022SQPH-!CVp(%f$Br7!UytSOLJ{W@ZFO_(THK{JlMynW#v{v-a*T zfMmPdEWc1DbJqWVks>!kBnAKqMb$PuekK>?0+ds;#ThdH1j_W4DKdsJG8Ul;qO2n0 z#IJ1jr{*iW$(WZWsE0n`c;fQ!l&-AnmjxZO1uWyz`0VP>&nP`#itsL#`S=Q!g`M=rU9)45( zJ;-|dRq-b5&z?byo>|{)?5r=n76A4nTALlSzLiw~v~31J<>9PP?;rs31pu_(obw)r zY+jPY;tVGXi|p)da{-@gE-UCa`=5eu%D;v=_nFJ?`&K)q7e9d`Nfk3?MdhZarb|T3 z%nS~f&t(1g5dY)AIcd$w!z`Siz!&j_=v7hZlnI21XuE|xfmo0(WD10T)!}~_HYW!e zew}L+XmwuzeT6wtxJd`dZ#@7*BLgIEKY9Xv>st^p3dp{^Xswa2bB{85{^$B13tWnB z;Y>jyQ|9&zk7RNsqAVGs--K+z0uqo1bf5|}fi5rtEMN^BfHQCd-XH*kfJhJnmIE$G z0%<@5vOzxB0181d*a3EfYH$G5fqKvcPJ%XY23!PJzzuK<41h;K3WmW;Fah3yX$XSw z5EY_9s*o0>51B&N5F1(uc|$=^I1~fLLy3?Ol0f;;Ca4%HgQ}rJP(Ab`bQ-z{U4#0d z2hboi2K@njgb|nm(_szR0JebHusa+GN5aeCM0gdP2N%HG;Yzp`J`T6S7vUT504#-H z!jlL<$Or?`Mpy_N@kBz9SR?@vA#0H$qyni$nvf2p8@Y{0k#Xb$28W?xm>3qu8RLgp zjNxKdVb)?wFx8l2m{v>|<~C*!GlBVnrDD~wrdTJeKXwT=5u1%I#8zOBU|X=4u>;s) z>^mF|$G{ol9B_WP7+f-LHLe7=57&&lfa}8z;U@8Tyei%l?}87(bMRt(A-)QK9Dg3) zj~~XrCy)tR1Z#p1A(kK{Y$Q|=8VKhI{e%(1G*N-5Pjn)N5P8I0VkxnX*g?EW941ba z6iJ387g8iCnY4jaNopcpCOsy-A(P2EWJhusSwLP-t|XrzUnLKcKTwn?CKOLf97RIe zPB}`sKzTrUL#0v;sBY9)s+hW+T2H-1eM)^VN0T#`^Oxhvt&^*fYnAJldnHel*Ozyf zUoM{~Um<@={-*r60#U(0!Bc^wuvVc);k3d%g-J!4qLpHZVwz%!VuRu}#Ze`^l7W)9 z5>Kf>>9Eozr6C$Z)1`URxU@~QI@)F0FdauXr2Es8>BaOP=)Lp_WhG@>R;lZ?BJkMlIuMhw8ApiF&yDYW2hFJ?fJhni{?u z85&g@mo&yT8JcdI$(rSw=QPK(Xj%)k1X|@<=e1rim6`6$RAwc!i#egKuI;BS(LSWz zt39n_sIypSqfWEV6J3%nTQ@-4i zi$R;gsG*9XzhRzXqv2yCs*$VFDx+GXJH|L;wsDH_KI2;^u!)^Xl1YupO;gy^-c(?^ z&$Q1BYvyPsG^;hc$D**@Sy`+`)}T4VJji^bd7Jqw3q6Zii=7tT7GEswEK@D(EFW1Z zSp`^awCb?>!`j4}Yh7b~$A)U-W3$et-R8BesV(1jzwLcHnq9En7Q0Tn&-M=XBKs!$ zF$X<|c!#|X_tWYh)GZit z(Q)Cp9CDE^WG;+fcyOWARoj*0TI>4EP1lX*cEoMO-Pk?Z{kZ!p4@(b`M~lalr<3Oz z&kJ6Nm#vN_+kA5{dW4@^Vjg_`q%qU1ULk& z3Fr!>1V#i_2R;ij2@(Z$1jE4r!MlPVFVbHmT+|iPIq0wy5aS{>yK?9ZAjVh%SOwMWgFjair&;wpi!{CU}&@N=Eg#~ zLQ&zpEzVmGY{hI9Z0+4-0xS$$Xe-OToc?Y*V;rTcf_ zb_jRe-RZjXSeas3UfIyD;9afd%<`i0x4T#DzE)vdabOQ=k7SRuGN`h>O0Q~1)u-yD z>VX=Mn&!Rgd$;YK+Q-}1zu#?t(*cbG#Ronf6db&N$oEidtwC+YVcg-Y!_VuY>bk#Y ze_ww@?MU&F&qswvrN_dLb=5o6*Egs)ls3YRlE$&)amR1{;Ppd$6RYV^Go!iq1UMl% z@#4q$AMc(FJlT1QeX8jv{h#)>&{~RGq1N2iiMFIRX?sk2-|2wUogK~{EkB$8eDsX= znVPf8XG_nK&J~=SIiGia@9y}|z3FhX{g&gcj=lwb=lWgyFW&aLedUh- zof`v-2Kw$UzI*>(+&$@i-u=-BsSjR1%z8NeX#HdC`Hh-Z(6xI-`hmHDqv!v)W&&nrf>M(RhcN6(D;jNN*%^u_SYjF;2ng}*8Ow)d6M ztDk;%`@Lsk$;9w$(d(H%O5UixIr`T2ZRcd@TL_}3lqFC*nw=uzyHmf zH4Npgx>PFzzlIi8tXM8Cp*Z!O7aUhYkvm?&rHWsn+7-h(KdI?VwAOS1s)C4V9>YKn@W)hugA2c#_`1qK)izaeFcB16kRlDR%);mY zBY5$(C9qCZkjo1^mMz2Q{nD~C=@1t$TevAi4lxDU!A|_RCxO?6#E=Cf%10{H-D~3b zCfm5KRaq#{Uo>!d%#Ku?y&xk2et0v1fzCQrY7p6jJ}bI{z1wu`>{F2pxiq-4wvCTI ztKh8U4d?y<^q}3*AII)Z8XgS+`tP3xc6|FkpCleEp~I0e1A`ym#mRi|ij_!fcvUjg zl68<^?+ZH8Y!&x|#=LaniizO~q5io?T^XgpCD`pNI|Rwb$sf95Ie;k@FKy6#H<@Kq z9AKz!44<>GD-(y;h~y_I`B*ADm=&-*vCeDW&s^H2_`q?l?iXn~lPfc(gPSG4&O|r6 zj1Gik1k3CXw~O(lD9PnWV1s_^ff>c&GZy-VQ{>5KJ20}^#+3;hQ!^B)9u=Ebvv-QH zzB*IIPj>}klWF7lG+0=?X5eH&MRukC>XdjShK=h(JXzO6apJfseWJ*P_@1%cF?NC! zf@P$RB`}~EJ5|OJ@dFOX1qq8P)XzMnV}HMf$CG|0xo!!AQi% z`9j7xHidUK7ZPeKk6}}I+m*Mv+6pAh_X+uL$Nkc;* zP;zf(X>4Tx07wm;mUmQB*%pV-y*Itk5+Wca^cs2zAksTX6$DXM^`x7XQc?|s+0 z08spb1j2M!0f022SQPH-!CVp(%f$Br7!UytSOLJ{W@ZFO_(THK{JlMynW#v{v-a*T zfMmPdEWc1DbJqWVks>!kBnAKqMb$PuekK>?0+ds;#ThdH1j_W4DKdsJG8Ul;qO2n0 z#IJ1jr{*iW$(WZWsE0n`c;fQ!l&-AnmjxZO1uWyz`0VP>&nP`#itsL#`S=Q!g`M=rU9)45( zJ;-|dRq-b5&z?byo>|{)?5r=n76A4nTALlSzLiw~v~31J<>9PP?;rs31pu_(obw)r zY+jPY;tVGXi|p)da{-@gE-UCa`=5eu%D;v=_nFJ?`&K)q7e9d`Nfk3?MdhZarb|T3 z%nS~f&t(1g5dY)AIcd$w!z`Siz!&j_=v7hZlnI21XuE|xfmo0(WD10T)!}~_HYW!e zew}L+XmwuzeT6wtxJd`dZ#@7*BLgIEKY9Xv>st^p3dp{^Xswa2bB{85{^$B13tWnB z;Y>jyQ|9&zk7RNsqAVGs--K+z0uqo1bf5|}fi5rtEMN^BfHQCd-XH*kfJhJnmIE$G z0%<@5vOzxB0181d*a3EfYH$G5fqKvcPJ%XY23!PJzzuK<41h;K3WmW;Fah3yX$XSw z5EY_9s*o0>51B&N5F1(uc|$=^I1~fLLy3?Ol0f;;Ca4%HgQ}rJP(Ab`bQ-z{U4#0d z2hboi2K@njgb|nm(_szR0JebHusa+GN5aeCM0gdP2N%HG;Yzp`J`T6S7vUT504#-H z!jlL<$Or?`Mpy_N@kBz9SR?@vA#0H$qyni$nvf2p8@Y{0k#Xb$28W?xm>3qu8RLgp zjNxKdVb)?wFx8l2m{v>|<~C*!GlBVnrDD~wrdTJeKXwT=5u1%I#8zOBU|X=4u>;s) z>^mF|$G{ol9B_WP7+f-LHLe7=57&&lfa}8z;U@8Tyei%l?}87(bMRt(A-)QK9Dg3) zj~~XrCy)tR1Z#p1A(kK{Y$Q|=8VKhI{e%(1G*N-5Pjn)N5P8I0VkxnX*g?EW941ba z6iJ387g8iCnY4jaNopcpCOsy-A(P2EWJhusSwLP-t|XrzUnLKcKTwn?CKOLf97RIe zPB}`sKzTrUL#0v;sBY9)s+hW+T2H-1eM)^VN0T#`^Oxhvt&^*fYnAJldnHel*Ozyf zUoM{~Um<@={-*r60#U(0!Bc^wuvVc);k3d%g-J!4qLpHZVwz%!VuRu}#Ze`^l7W)9 z5>Kf>>9Eozr6C$Z)1`URxU@~QI@)F0FdauXr2Es8>BaOP=)Lp_WhG@>R;lZ?BJkMlIuMhw8ApiF&yDYW2hFJ?fJhni{?u z85&g@mo&yT8JcdI$(rSw=QPK(Xj%)k1X|@<=e1rim6`6$RAwc!i#egKuI;BS(LSWz zt39n_sIypSqfWEV6J3%nTQ@-4i zi$R;gsG*9XzhRzXqv2yCs*$VFDx+GXJH|L;wsDH_KI2;^u!)^Xl1YupO;gy^-c(?^ z&$Q1BYvyPsG^;hc$D**@Sy`+`)}T4VJji^bd7Jqw3q6Zii=7tT7GEswEK@D(EFW1Z zSp`^awCb?>!`j4}Yh7b~$A)U-W3$et-R8BesV(1jzwLcHnq9En7Q0Tn&-M=XBKs!$ zF$X<|c!#|X_tWYh)GZit z(Q)Cp9CDE^WG;+fcyOWARoj*0TI>4EP1lX*cEoMO-Pk?Z{kZ!p4@(b`M~lalr<3Oz z&kJ6Nm#vN_+kA5{dW4@^Vjg_`q%qU1ULk& z3Fr!>1V#i_2R;ij2@(Z$1jE4r!MlPVFVbHmT+|iPIq0wy5aS{>yK?9ZAjVh%SOwMWgFjair&;wpi!{CU}&@N=Eg#~ zLQ&zpEzVmGY{hI9Z0+4-0xS$$Xe-OToc?Y*V;rTcf_ zb_jRe-RZjXSeas3UfIyD;9afd%<`i0x4T#DzE)vdabOQ=k7SRuGN`h>O0Q~1)u-yD z>VX=Mn&!Rgd$;YK+Q-}1zu#?t(*cbG#Ronf6db&N$oEidtwC+YVcg-Y!_VuY>bk#Y ze_ww@?MU&F&qswvrN_dLb=5o6*Egs)ls3YRlE$&)amR1{;Ppd$6RYV^Go!iq1UMl% z@#4q$AMc(FJlT1QeX8jv{h#)>&{~RGq1N2iiMFIRX?sk2-|2wUogK~{EkB$8eDsX= znVPf8XG_nK&J~=SIiGia@9y}|z3FhX{g&gcj=lwb=lWgyFW&aLedUh- zof`v-2Kw$UzI*>(+&$@i-u=-BsSjR1%z8NeX#HdC`Hh-Z(6xI-`hmHDqv!v)W&&nrf>M(RhcN6(D;jNN*%^u_SYjF;2ng}*8Ow)d6M ztDk;%`@Lsk$;9w$(d(H%O5UixIr`T2ZRcd@d|TYGF%RT%%>+t<1cSaefa zP!|v(I7yU%EM$pYCQ1;HV4|Y&k+8(5M2v)lpm7G!sEJ^7{vjBApd==n4kdshGfuNP zLNGdXii-@$MuM8b*7bF7uiv?&-EDhM+uNSDcAli|d7t0!JLi1gcW&>IkR;sR{Pzsl z?5ku+S`G=bG!4~~B$X#=lJ_D_(?%r;gV4|)*0cjqmG*C%uRO;CBAFE|X}(bHvb$b{ zBt1suHnTea;XDIcfojGG!C1K{;~HpdYpWwOtrKQ@*6DEd zO@^5@n-sRZgQ37&wx{*kWD07sl4Sy5+;k<(;>`5O4(Dl#7n?RF$d-Z{4h3suW@o9{ zWGBlcW7B;K-Knr7sN${6xXR3fDqac}krP+@xVvbvVK&vBz;s8%8fqBz0wdY@x{W@jH}eJeI#ciEL`Zs#s()U zEvQ8QMFo35@nhcwVLW3x$`N4+8`iq9f{Z|>;rLf$*mNwMX>)G7%n@|%k zdQ!o#nhc|adsjP>Rj^!Ux7;F0gN2JoL2=5Jiy^%BUI0hP3{8X(&@Q2AjT`sRF_*o4 zx|3!(gk8fEt+I)kkCIW35|+>7%&w|pTT49I$RHYawT@x;Z#)Gh;kKK_!4%gMxop!+ zY%HU7t|x%b2tUs6zSaQFah7-0wc=ok>#0n}b#8Muzn|gFp0U1)L#NGMf^stC(~VWL zh>Igkx`n3@N~5l1a-=_}C79%Wq$=fMOw}&2ob->Ma?PIM&b^8DcAt{iCN8J9%ZGb@ zqD<;58kn%WnlOJ`+zfkF4EUljVslx3%VK1a_k=*gK-S5qQIB`NEG?FL}|@8A@>$9`9lC$`Ukk4ke~zq{z%K;V2jlZS)Xe z%`2m5=~8r;G+LApv7u=h=h&H0H+4pV2u}cO>+oYaDYsJ`x0Kbaob5pEM3byy1t+Yd zr{_G6?-;|MJfFpBL!BVcOw4JC0DZL4jcZI~fBc{qn@*&obi#P~O9k&NGlxXy2_Zqu z4AT+L946qlNB&kxjklksIQ1bibw9~!h#^cz!$Hm-oH^Ut5In-76ty)pT+wOx<1h1N zTTS@zW5J|acJszkY_GS0PKL38ysxIa-8lTHi|c)z|5ZVMY^#h@JYADP zhhgmeR>2z{UY9Z!*SqNhC_xRwJ`HxKgbH^mr547=M|rEqI!s|R%!cmm^5gR%^Sx|@ z#)wu-6pAMbh8UQhn;OdD#hkTKOY!No_(c7=$$e@_5FwuK#jJ<+LFSXFi)xeFh zMdDMv14N2Gg$!g5hGh08c_BgMb!_4)>#xn{b=1NQ#<{`o@3{=Kd)-OcR z9fACeS-??d2abq0W7&>A7_6J>vAO$AYt;r>ebo*wUh+E`_ zOVrcS?*wS!4U>vABTJkj_Z^sw5{@eWt7|+=0!$k0LIhoQ+D*w~)ZXl()^5hZIJ1l! k3kfqko<06O8L#5~3mrKpj{Is>w*UYD07*qoM6N<$f?pec9{>OV literal 0 HcmV?d00001 diff --git a/tools/gyp/test/mac/app-bundle/TestApp/TestApp-Info.plist b/tools/gyp/test/mac/app-bundle/TestApp/TestApp-Info.plist new file mode 100644 index 00000000000000..e005852f9f9bfe --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/TestApp/TestApp-Info.plist @@ -0,0 +1,34 @@ + + + + + BuildMachineOSBuild + Doesn't matter, will be overwritten + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.google.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ause + CFBundleVersion + 1 + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tools/gyp/test/mac/app-bundle/TestApp/TestAppAppDelegate.h b/tools/gyp/test/mac/app-bundle/TestApp/TestAppAppDelegate.h new file mode 100644 index 00000000000000..518645eae9d726 --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/TestApp/TestAppAppDelegate.h @@ -0,0 +1,13 @@ +// 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. + +#import + +@interface TestAppAppDelegate : NSObject { + NSWindow *window; +} + +@property (assign) IBOutlet NSWindow *window; + +@end diff --git a/tools/gyp/test/mac/app-bundle/TestApp/TestAppAppDelegate.m b/tools/gyp/test/mac/app-bundle/TestApp/TestAppAppDelegate.m new file mode 100644 index 00000000000000..9aafa420008ce7 --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/TestApp/TestAppAppDelegate.m @@ -0,0 +1,15 @@ +// 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. + +#import "TestAppAppDelegate.h" + +@implementation TestAppAppDelegate + +@synthesize window; + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +@end diff --git a/tools/gyp/test/mac/app-bundle/TestApp/main.m b/tools/gyp/test/mac/app-bundle/TestApp/main.m new file mode 100644 index 00000000000000..df6a12d065b226 --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/TestApp/main.m @@ -0,0 +1,10 @@ +// 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. + +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/tools/gyp/test/mac/app-bundle/empty.c b/tools/gyp/test/mac/app-bundle/empty.c new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/mac/app-bundle/test-assets-catalog.gyp b/tools/gyp/test/mac/app-bundle/test-assets-catalog.gyp new file mode 100644 index 00000000000000..25f94a12d0cf0d --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/test-assets-catalog.gyp @@ -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 --git a/tools/gyp/test/mac/app-bundle/test-error.gyp b/tools/gyp/test/mac/app-bundle/test-error.gyp new file mode 100644 index 00000000000000..370772cc31efbb --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/test-error.gyp @@ -0,0 +1,31 @@ +# 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': 'test_app', + 'product_name': 'Test App Gyp', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'TestApp/main.m', + 'TestApp/TestApp_Prefix.pch', + 'TestApp/TestAppAppDelegate.h', + 'TestApp/TestAppAppDelegate.m', + ], + 'mac_bundle_resources': [ + 'TestApp/English.lproj/InfoPlist-error.strings', + 'TestApp/English.lproj/MainMenu.xib', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Cocoa.framework', + ], + }, + 'xcode_settings': { + 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/app-bundle/test.gyp b/tools/gyp/test/mac/app-bundle/test.gyp new file mode 100644 index 00000000000000..21973c3623a482 --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/test.gyp @@ -0,0 +1,41 @@ +# 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 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', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Cocoa.framework', + ], + }, + 'xcode_settings': { + 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/archs/empty_main.cc b/tools/gyp/test/mac/archs/empty_main.cc new file mode 100644 index 00000000000000..237c8ce181774d --- /dev/null +++ b/tools/gyp/test/mac/archs/empty_main.cc @@ -0,0 +1 @@ +int main() {} diff --git a/tools/gyp/test/mac/archs/file.mm b/tools/gyp/test/mac/archs/file.mm new file mode 100644 index 00000000000000..d0b39d1f6d8bb4 --- /dev/null +++ b/tools/gyp/test/mac/archs/file.mm @@ -0,0 +1 @@ +MyInt f() { return 0; } diff --git a/tools/gyp/test/mac/archs/file_a.cc b/tools/gyp/test/mac/archs/file_a.cc new file mode 100644 index 00000000000000..7307873c8374fb --- /dev/null +++ b/tools/gyp/test/mac/archs/file_a.cc @@ -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 --git a/tools/gyp/test/mac/archs/file_a.h b/tools/gyp/test/mac/archs/file_a.h new file mode 100644 index 00000000000000..7439d131820b7e --- /dev/null +++ b/tools/gyp/test/mac/archs/file_a.h @@ -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 --git a/tools/gyp/test/mac/archs/file_b.cc b/tools/gyp/test/mac/archs/file_b.cc new file mode 100644 index 00000000000000..72d59cbfb4661a --- /dev/null +++ b/tools/gyp/test/mac/archs/file_b.cc @@ -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 --git a/tools/gyp/test/mac/archs/file_b.h b/tools/gyp/test/mac/archs/file_b.h new file mode 100644 index 00000000000000..eb272ece5504e4 --- /dev/null +++ b/tools/gyp/test/mac/archs/file_b.h @@ -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 --git a/tools/gyp/test/mac/archs/file_c.cc b/tools/gyp/test/mac/archs/file_c.cc new file mode 100644 index 00000000000000..ca39f7a6719f07 --- /dev/null +++ b/tools/gyp/test/mac/archs/file_c.cc @@ -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 --git a/tools/gyp/test/mac/archs/file_d.cc b/tools/gyp/test/mac/archs/file_d.cc new file mode 100644 index 00000000000000..c40911cdca88fe --- /dev/null +++ b/tools/gyp/test/mac/archs/file_d.cc @@ -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 --git a/tools/gyp/test/mac/archs/header.h b/tools/gyp/test/mac/archs/header.h new file mode 100644 index 00000000000000..0716e500c5a69d --- /dev/null +++ b/tools/gyp/test/mac/archs/header.h @@ -0,0 +1 @@ +typedef int MyInt; diff --git a/tools/gyp/test/mac/archs/my_file.cc b/tools/gyp/test/mac/archs/my_file.cc new file mode 100644 index 00000000000000..94216a74df6c36 --- /dev/null +++ b/tools/gyp/test/mac/archs/my_file.cc @@ -0,0 +1,4 @@ +/* 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. */ +int x = 1; diff --git a/tools/gyp/test/mac/archs/my_main_file.cc b/tools/gyp/test/mac/archs/my_main_file.cc new file mode 100644 index 00000000000000..f1fa06f2769cb5 --- /dev/null +++ b/tools/gyp/test/mac/archs/my_main_file.cc @@ -0,0 +1,9 @@ +/* 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 +extern int x; +int main() { + printf("hello, world %d\n", x); +} + diff --git a/tools/gyp/test/mac/archs/test-archs-multiarch.gyp b/tools/gyp/test/mac/archs/test-archs-multiarch.gyp new file mode 100644 index 00000000000000..567e8a6653ce86 --- /dev/null +++ b/tools/gyp/test/mac/archs/test-archs-multiarch.gyp @@ -0,0 +1,92 @@ +# 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': 'static_32_64', + 'type': 'static_library', + 'sources': [ 'my_file.cc' ], + 'xcode_settings': { + 'ARCHS': [ 'i386', 'x86_64' ], + }, + }, + { + 'target_name': 'shared_32_64', + 'type': 'shared_library', + 'sources': [ 'my_file.cc' ], + 'xcode_settings': { + 'ARCHS': [ 'i386', 'x86_64' ], + }, + }, + { + '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' ], + 'xcode_settings': { + 'ARCHS': [ 'i386', 'x86_64' ], + }, + }, + { + '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' ], + 'xcode_settings': { + 'ARCHS': [ 'i386', 'x86_64' ], + }, + }, + { + 'target_name': 'exe_32_64_bundle', + 'product_name': 'Test App', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ 'empty_main.cc' ], + 'xcode_settings': { + 'ARCHS': [ 'i386', 'x86_64' ], + }, + }, + # This only needs to compile. + { + 'target_name': 'precompiled_prefix_header_mm_32_64', + 'type': 'shared_library', + 'sources': [ 'file.mm', ], + 'xcode_settings': { + 'GCC_PREFIX_HEADER': 'header.h', + '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 --git a/tools/gyp/test/mac/archs/test-archs-x86_64.gyp b/tools/gyp/test/mac/archs/test-archs-x86_64.gyp new file mode 100644 index 00000000000000..d11a896273cab7 --- /dev/null +++ b/tools/gyp/test/mac/archs/test-archs-x86_64.gyp @@ -0,0 +1,27 @@ +# 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': 'lib', + 'product_name': 'Test64', + 'type': 'static_library', + 'sources': [ 'my_file.cc' ], + 'xcode_settings': { + 'ARCHS': [ 'x86_64' ], + }, + }, + { + 'target_name': 'exe', + 'product_name': 'Test64', + 'type': 'executable', + 'dependencies': [ 'lib' ], + 'sources': [ 'my_main_file.cc' ], + 'xcode_settings': { + 'ARCHS': [ 'x86_64' ], + }, + }, + ] +} diff --git a/tools/gyp/test/mac/archs/test-dependencies.gyp b/tools/gyp/test/mac/archs/test-dependencies.gyp new file mode 100644 index 00000000000000..0431f5f2f4fab2 --- /dev/null +++ b/tools/gyp/test/mac/archs/test-dependencies.gyp @@ -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 --git a/tools/gyp/test/mac/archs/test-no-archs.gyp b/tools/gyp/test/mac/archs/test-no-archs.gyp new file mode 100644 index 00000000000000..8f3b6b47cc163f --- /dev/null +++ b/tools/gyp/test/mac/archs/test-no-archs.gyp @@ -0,0 +1,21 @@ +# 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': 'lib', + 'product_name': 'Test', + 'type': 'static_library', + 'sources': [ 'my_file.cc' ], + }, + { + 'target_name': 'exe', + 'product_name': 'Test', + 'type': 'executable', + 'dependencies': [ 'lib' ], + 'sources': [ 'my_main_file.cc' ], + }, + ] +} diff --git a/tools/gyp/test/mac/archs/test-valid-archs.gyp b/tools/gyp/test/mac/archs/test-valid-archs.gyp new file mode 100644 index 00000000000000..c90ec1fe9b3b0b --- /dev/null +++ b/tools/gyp/test/mac/archs/test-valid-archs.gyp @@ -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 --git a/tools/gyp/test/mac/bundle-resources/change.sh b/tools/gyp/test/mac/bundle-resources/change.sh new file mode 100644 index 00000000000000..6d0fe6c7c279ac --- /dev/null +++ b/tools/gyp/test/mac/bundle-resources/change.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +tr a-z A-Z < "${1}" > "${2}" diff --git a/tools/gyp/test/mac/bundle-resources/executable-file.sh b/tools/gyp/test/mac/bundle-resources/executable-file.sh new file mode 100644 index 00000000000000..796953a1a2cf23 --- /dev/null +++ b/tools/gyp/test/mac/bundle-resources/executable-file.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +echo echo echo echo cho ho o o diff --git a/tools/gyp/test/mac/bundle-resources/secret.txt b/tools/gyp/test/mac/bundle-resources/secret.txt new file mode 100644 index 00000000000000..8baef1b4abc478 --- /dev/null +++ b/tools/gyp/test/mac/bundle-resources/secret.txt @@ -0,0 +1 @@ +abc diff --git a/tools/gyp/test/mac/bundle-resources/test.gyp b/tools/gyp/test/mac/bundle-resources/test.gyp new file mode 100644 index 00000000000000..af034ce3f4d177 --- /dev/null +++ b/tools/gyp/test/mac/bundle-resources/test.gyp @@ -0,0 +1,59 @@ +# 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': 'resource', + 'type': 'executable', + 'mac_bundle': 1, + 'mac_bundle_resources': [ + 'secret.txt', + 'executable-file.sh', + ], + }, + # A rule with process_outputs_as_mac_bundle_resources should copy files + # into the Resources folder. + { + 'target_name': 'source_rule', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'secret.txt', + ], + 'rules': [ + { + 'rule_name': 'bundlerule', + 'extension': 'txt', + 'outputs': [ + '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).txt', + ], + 'action': ['./change.sh', '<(RULE_INPUT_PATH)', '<@(_outputs)'], + 'message': 'Running rule on <(RULE_INPUT_PATH)', + 'process_outputs_as_mac_bundle_resources': 1, + }, + ], + }, + # So should an ordinary rule acting on mac_bundle_resources. + { + 'target_name': 'resource_rule', + 'type': 'executable', + 'mac_bundle': 1, + 'mac_bundle_resources': [ + 'secret.txt', + ], + 'rules': [ + { + 'rule_name': 'bundlerule', + 'extension': 'txt', + 'outputs': [ + '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).txt', + ], + 'action': ['./change.sh', '<(RULE_INPUT_PATH)', '<@(_outputs)'], + 'message': 'Running rule on <(RULE_INPUT_PATH)', + }, + ], + }, + ], +} + diff --git a/tools/gyp/test/mac/cflags/ccfile.cc b/tools/gyp/test/mac/cflags/ccfile.cc new file mode 100644 index 00000000000000..1a54d18eec7122 --- /dev/null +++ b/tools/gyp/test/mac/cflags/ccfile.cc @@ -0,0 +1,7 @@ +#ifdef CFLAG +#error CFLAG should not be set +#endif + +#ifndef CCFLAG +#error CCFLAG should be set +#endif diff --git a/tools/gyp/test/mac/cflags/ccfile_withcflags.cc b/tools/gyp/test/mac/cflags/ccfile_withcflags.cc new file mode 100644 index 00000000000000..de078a06417628 --- /dev/null +++ b/tools/gyp/test/mac/cflags/ccfile_withcflags.cc @@ -0,0 +1,7 @@ +#ifndef CFLAG +#error CFLAG should be set +#endif + +#ifndef CCFLAG +#error CCFLAG should be set +#endif diff --git a/tools/gyp/test/mac/cflags/cfile.c b/tools/gyp/test/mac/cflags/cfile.c new file mode 100644 index 00000000000000..0af9d0af5da474 --- /dev/null +++ b/tools/gyp/test/mac/cflags/cfile.c @@ -0,0 +1,7 @@ +#ifndef CFLAG +#error CFLAG should be set +#endif + +#ifdef CCFLAG +#error CCFLAG should not be set +#endif diff --git a/tools/gyp/test/mac/cflags/cppfile.cpp b/tools/gyp/test/mac/cflags/cppfile.cpp new file mode 100644 index 00000000000000..1a54d18eec7122 --- /dev/null +++ b/tools/gyp/test/mac/cflags/cppfile.cpp @@ -0,0 +1,7 @@ +#ifdef CFLAG +#error CFLAG should not be set +#endif + +#ifndef CCFLAG +#error CCFLAG should be set +#endif diff --git a/tools/gyp/test/mac/cflags/cppfile_withcflags.cpp b/tools/gyp/test/mac/cflags/cppfile_withcflags.cpp new file mode 100644 index 00000000000000..de078a06417628 --- /dev/null +++ b/tools/gyp/test/mac/cflags/cppfile_withcflags.cpp @@ -0,0 +1,7 @@ +#ifndef CFLAG +#error CFLAG should be set +#endif + +#ifndef CCFLAG +#error CCFLAG should be set +#endif diff --git a/tools/gyp/test/mac/cflags/cxxfile.cxx b/tools/gyp/test/mac/cflags/cxxfile.cxx new file mode 100644 index 00000000000000..1a54d18eec7122 --- /dev/null +++ b/tools/gyp/test/mac/cflags/cxxfile.cxx @@ -0,0 +1,7 @@ +#ifdef CFLAG +#error CFLAG should not be set +#endif + +#ifndef CCFLAG +#error CCFLAG should be set +#endif diff --git a/tools/gyp/test/mac/cflags/cxxfile_withcflags.cxx b/tools/gyp/test/mac/cflags/cxxfile_withcflags.cxx new file mode 100644 index 00000000000000..de078a06417628 --- /dev/null +++ b/tools/gyp/test/mac/cflags/cxxfile_withcflags.cxx @@ -0,0 +1,7 @@ +#ifndef CFLAG +#error CFLAG should be set +#endif + +#ifndef CCFLAG +#error CCFLAG should be set +#endif diff --git a/tools/gyp/test/mac/cflags/mfile.m b/tools/gyp/test/mac/cflags/mfile.m new file mode 100644 index 00000000000000..0af9d0af5da474 --- /dev/null +++ b/tools/gyp/test/mac/cflags/mfile.m @@ -0,0 +1,7 @@ +#ifndef CFLAG +#error CFLAG should be set +#endif + +#ifdef CCFLAG +#error CCFLAG should not be set +#endif diff --git a/tools/gyp/test/mac/cflags/mmfile.mm b/tools/gyp/test/mac/cflags/mmfile.mm new file mode 100644 index 00000000000000..1a54d18eec7122 --- /dev/null +++ b/tools/gyp/test/mac/cflags/mmfile.mm @@ -0,0 +1,7 @@ +#ifdef CFLAG +#error CFLAG should not be set +#endif + +#ifndef CCFLAG +#error CCFLAG should be set +#endif diff --git a/tools/gyp/test/mac/cflags/mmfile_withcflags.mm b/tools/gyp/test/mac/cflags/mmfile_withcflags.mm new file mode 100644 index 00000000000000..de078a06417628 --- /dev/null +++ b/tools/gyp/test/mac/cflags/mmfile_withcflags.mm @@ -0,0 +1,7 @@ +#ifndef CFLAG +#error CFLAG should be set +#endif + +#ifndef CCFLAG +#error CCFLAG should be set +#endif diff --git a/tools/gyp/test/mac/cflags/test.gyp b/tools/gyp/test/mac/cflags/test.gyp new file mode 100644 index 00000000000000..d330a548f647ea --- /dev/null +++ b/tools/gyp/test/mac/cflags/test.gyp @@ -0,0 +1,132 @@ +# 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': 'mytarget', + 'type': 'shared_library', + 'sources': [ + 'cfile.c', + 'mfile.m', + 'ccfile.cc', + 'cppfile.cpp', + 'cxxfile.cxx', + 'mmfile.mm', + ], + 'xcode_settings': { + # Normally, defines would go in 'defines' instead. This is just for + # testing. + 'OTHER_CFLAGS': [ + '-DCFLAG', + ], + 'OTHER_CPLUSPLUSFLAGS': [ + '-DCCFLAG', + ], + 'GCC_C_LANGUAGE_STANDARD': 'c99', + }, + }, + { + 'target_name': 'mytarget_reuse_cflags', + 'type': 'shared_library', + 'sources': [ + 'cfile.c', + 'mfile.m', + 'ccfile_withcflags.cc', + 'cppfile_withcflags.cpp', + 'cxxfile_withcflags.cxx', + 'mmfile_withcflags.mm', + ], + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-DCFLAG', + ], + 'OTHER_CPLUSPLUSFLAGS': [ + '$OTHER_CFLAGS', + '-DCCFLAG', + ], + # This is a C-only flag, to check these don't get added to C++ files. + 'GCC_C_LANGUAGE_STANDARD': 'c99', + }, + }, + { + 'target_name': 'mytarget_inherit_cflags', + 'type': 'shared_library', + 'sources': [ + 'cfile.c', + 'mfile.m', + 'ccfile_withcflags.cc', + 'cppfile_withcflags.cpp', + 'cxxfile_withcflags.cxx', + 'mmfile_withcflags.mm', + ], + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-DCFLAG', + ], + 'OTHER_CPLUSPLUSFLAGS': [ + '$inherited', + '-DCCFLAG', + ], + 'GCC_C_LANGUAGE_STANDARD': 'c99', + }, + }, + { + 'target_name': 'mytarget_inherit_cflags_parens', + 'type': 'shared_library', + 'sources': [ + 'cfile.c', + 'mfile.m', + 'ccfile_withcflags.cc', + 'cppfile_withcflags.cpp', + 'cxxfile_withcflags.cxx', + 'mmfile_withcflags.mm', + ], + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-DCFLAG', + ], + 'OTHER_CPLUSPLUSFLAGS': [ + '$(inherited)', + '-DCCFLAG', + ], + 'GCC_C_LANGUAGE_STANDARD': 'c99', + }, + }, + { + 'target_name': 'mytarget_inherit_cflags_braces', + 'type': 'shared_library', + 'sources': [ + 'cfile.c', + 'mfile.m', + 'ccfile_withcflags.cc', + 'cppfile_withcflags.cpp', + 'cxxfile_withcflags.cxx', + 'mmfile_withcflags.mm', + ], + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-DCFLAG', + ], + 'OTHER_CPLUSPLUSFLAGS': [ + '${inherited}', + '-DCCFLAG', + ], + 'GCC_C_LANGUAGE_STANDARD': 'c99', + }, + }, + { + 'target_name': 'ansi_standard', + 'type': 'shared_library', + 'sources': [ + 'cfile.c', + ], + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-DCFLAG', + ], + 'GCC_C_LANGUAGE_STANDARD': 'ansi', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/clang-cxx-language-standard/c++11.cc b/tools/gyp/test/mac/clang-cxx-language-standard/c++11.cc new file mode 100644 index 00000000000000..756dc1c7e6aa49 --- /dev/null +++ b/tools/gyp/test/mac/clang-cxx-language-standard/c++11.cc @@ -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. + +static_assert(__cplusplus == 201103L, "wrong c++ standard version"); + +int main() { return 0; } + diff --git a/tools/gyp/test/mac/clang-cxx-language-standard/c++98.cc b/tools/gyp/test/mac/clang-cxx-language-standard/c++98.cc new file mode 100644 index 00000000000000..a6a00c70f497f3 --- /dev/null +++ b/tools/gyp/test/mac/clang-cxx-language-standard/c++98.cc @@ -0,0 +1,24 @@ +// 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 __cplusplus != 199711L +#error wrong c++ standard version +#endif + +enum cxx11_keywords { + alignas, + alignof, + char16_t, + char32_t, + constexpr, + decltype, + noexcept, + nullptr, + override, + static_assert, + thread_local, +}; + +int main() { return 0; } + diff --git a/tools/gyp/test/mac/clang-cxx-language-standard/clang-cxx-language-standard.gyp b/tools/gyp/test/mac/clang-cxx-language-standard/clang-cxx-language-standard.gyp new file mode 100644 index 00000000000000..eb60bbd0e88a97 --- /dev/null +++ b/tools/gyp/test/mac/clang-cxx-language-standard/clang-cxx-language-standard.gyp @@ -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. +{ + 'make_global_settings': [ + ['CC', '/usr/bin/clang'], + ['CXX', '/usr/bin/clang++'], + ], + 'targets': [ + { + 'target_name': 'c++98', + 'type': 'executable', + 'sources': [ 'c++98.cc', ], + 'xcode_settings': { + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + 'CLANG_CXX_LANGUAGE_STANDARD': 'c++98', + }, + }, + { + 'target_name': 'c++11', + 'type': 'executable', + 'sources': [ 'c++11.cc', ], + 'xcode_settings': { + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + 'CLANG_CXX_LANGUAGE_STANDARD': 'c++0x', + }, + }, + ], +} + diff --git a/tools/gyp/test/mac/clang-cxx-library/clang-cxx-library.gyp b/tools/gyp/test/mac/clang-cxx-library/clang-cxx-library.gyp new file mode 100644 index 00000000000000..67006e50a0188c --- /dev/null +++ b/tools/gyp/test/mac/clang-cxx-library/clang-cxx-library.gyp @@ -0,0 +1,32 @@ +# 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'], + ['CXX', '/usr/bin/clang++'], + ], + 'targets': [ + { + 'target_name': 'libc++', + 'type': 'executable', + 'sources': [ 'libc++.cc', ], + 'xcode_settings': { + 'CC': 'clang', + # libc++ requires OS X 10.7+. + 'MACOSX_DEPLOYMENT_TARGET': '10.7', + 'CLANG_CXX_LIBRARY': 'libc++', + }, + }, + { + 'target_name': 'libstdc++', + 'type': 'executable', + 'sources': [ 'libstdc++.cc', ], + 'xcode_settings': { + 'CC': 'clang', + 'CLANG_CXX_LIBRARY': 'libstdc++', + }, + }, + ], +} + diff --git a/tools/gyp/test/mac/clang-cxx-library/libc++.cc b/tools/gyp/test/mac/clang-cxx-library/libc++.cc new file mode 100644 index 00000000000000..b8d6e6b3e2c277 --- /dev/null +++ b/tools/gyp/test/mac/clang-cxx-library/libc++.cc @@ -0,0 +1,11 @@ +// 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 +#ifndef _LIBCPP_VERSION +#error expected std library: libc++ +#endif + +int main() { std::string x; return x.size(); } + diff --git a/tools/gyp/test/mac/clang-cxx-library/libstdc++.cc b/tools/gyp/test/mac/clang-cxx-library/libstdc++.cc new file mode 100644 index 00000000000000..474dbf350d2539 --- /dev/null +++ b/tools/gyp/test/mac/clang-cxx-library/libstdc++.cc @@ -0,0 +1,11 @@ +// 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 +#ifndef __GLIBCXX__ +#error expected std library: libstdc++ +#endif + +int main() { std::string x; return x.size(); } + diff --git a/tools/gyp/test/mac/copies-with-xcode-envvars/copies-with-xcode-envvars.gyp b/tools/gyp/test/mac/copies-with-xcode-envvars/copies-with-xcode-envvars.gyp new file mode 100644 index 00000000000000..c1b1241fb7a059 --- /dev/null +++ b/tools/gyp/test/mac/copies-with-xcode-envvars/copies-with-xcode-envvars.gyp @@ -0,0 +1,87 @@ +# Copyright (c) 2016 Mark Callow. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# For testing use of the UI settings & environment variables +# available in Xcode's PBXCopyFilesBuildPhase. +{ +'targets': [ + { + 'target_name': 'copies-with-xcode-envvars', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ 'empty.c' ], + 'conditions': [ + ['OS == "ios" or OS == "mac"', { + 'copies': [{ + 'destination': '$(BUILT_PRODUCTS_DIR)', + 'files': [ + 'file0', + ], + }, { + 'destination': '$(BUILT_PRODUCTS_DIR)/$(WRAPPER_NAME)', + 'files': [ + 'file1', + ], + }, { + 'destination': '<(PRODUCT_DIR)/$(EXECUTABLE_FOLDER_PATH)', + 'files': [ + 'file2', + ], + }, { + 'destination': '<(PRODUCT_DIR)/$(UNLOCALIZED_RESOURCES_FOLDER_PATH)', + 'files': [ + 'file3', + ], + }, { + 'destination': '<(PRODUCT_DIR)/$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/testimages', + 'files': [ + 'file4', + ], + }, { + 'destination': '$(BUILT_PRODUCTS_DIR)/$(JAVA_FOLDER_PATH)', + 'files': [ + 'file5', + ], + }, { + 'destination': '<(PRODUCT_DIR)/$(FRAMEWORKS_FOLDER_PATH)', + 'files': [ + 'file6', + ], + }, { + # NOTE: This is not an Xcode macro name but + # xcodeproj_file.py recognizes it and sends + # the output to the same place as + # $(FRAMEWORKS_FOLDER_PATH). xcode_emulation.py + # sets its value to an absolute path. + 'destination': '$(BUILT_FRAMEWORKS_DIR)', + 'files': [ + 'file7', + ], + }, { + 'destination': '<(PRODUCT_DIR)/$(SHARED_FRAMEWORKS_FOLDER_PATH)', + 'files': [ + 'file8', + ], + }, { + 'destination': '<(PRODUCT_DIR)/$(SHARED_SUPPORT_FOLDER_PATH)', + 'files': [ + 'file9', + ], + }, { + 'destination': '<(PRODUCT_DIR)/$(PLUGINS_FOLDER_PATH)', + 'files': [ + 'file10', + ], + }, { + 'destination': '<(PRODUCT_DIR)/$(XPCSERVICES_FOLDER_PATH)', + 'files': [ + 'file11', + ], + }], # copies + }], # OS == "ios" or OS == "mac" + ], # conditions + }], # targets +} + +# vim:ai:ts=4:sts=4:sw=2:expandtab:textwidth=70 diff --git a/tools/gyp/test/mac/copies-with-xcode-envvars/empty.c b/tools/gyp/test/mac/copies-with-xcode-envvars/empty.c new file mode 100644 index 00000000000000..237c8ce181774d --- /dev/null +++ b/tools/gyp/test/mac/copies-with-xcode-envvars/empty.c @@ -0,0 +1 @@ +int main() {} diff --git a/tools/gyp/test/mac/copies-with-xcode-envvars/file0 b/tools/gyp/test/mac/copies-with-xcode-envvars/file0 new file mode 100644 index 00000000000000..117889361f6cbf --- /dev/null +++ b/tools/gyp/test/mac/copies-with-xcode-envvars/file0 @@ -0,0 +1 @@ +file0 contents diff --git a/tools/gyp/test/mac/copies-with-xcode-envvars/file1 b/tools/gyp/test/mac/copies-with-xcode-envvars/file1 new file mode 100644 index 00000000000000..84d55c5759cf6b --- /dev/null +++ b/tools/gyp/test/mac/copies-with-xcode-envvars/file1 @@ -0,0 +1 @@ +file1 contents diff --git a/tools/gyp/test/mac/copies-with-xcode-envvars/file10 b/tools/gyp/test/mac/copies-with-xcode-envvars/file10 new file mode 100644 index 00000000000000..372e992ef9c43f --- /dev/null +++ b/tools/gyp/test/mac/copies-with-xcode-envvars/file10 @@ -0,0 +1 @@ +file10 contents diff --git a/tools/gyp/test/mac/copies-with-xcode-envvars/file11 b/tools/gyp/test/mac/copies-with-xcode-envvars/file11 new file mode 100644 index 00000000000000..923e760e1f1842 --- /dev/null +++ b/tools/gyp/test/mac/copies-with-xcode-envvars/file11 @@ -0,0 +1 @@ +file11 contents diff --git a/tools/gyp/test/mac/copies-with-xcode-envvars/file2 b/tools/gyp/test/mac/copies-with-xcode-envvars/file2 new file mode 100644 index 00000000000000..af1b8ae35db461 --- /dev/null +++ b/tools/gyp/test/mac/copies-with-xcode-envvars/file2 @@ -0,0 +1 @@ +file2 contents diff --git a/tools/gyp/test/mac/copies-with-xcode-envvars/file3 b/tools/gyp/test/mac/copies-with-xcode-envvars/file3 new file mode 100644 index 00000000000000..43f16f35220657 --- /dev/null +++ b/tools/gyp/test/mac/copies-with-xcode-envvars/file3 @@ -0,0 +1 @@ +file3 contents diff --git a/tools/gyp/test/mac/copies-with-xcode-envvars/file4 b/tools/gyp/test/mac/copies-with-xcode-envvars/file4 new file mode 100644 index 00000000000000..5f7270a0847cc6 --- /dev/null +++ b/tools/gyp/test/mac/copies-with-xcode-envvars/file4 @@ -0,0 +1 @@ +file4 contents diff --git a/tools/gyp/test/mac/copies-with-xcode-envvars/file5 b/tools/gyp/test/mac/copies-with-xcode-envvars/file5 new file mode 100644 index 00000000000000..41f47186bd2197 --- /dev/null +++ b/tools/gyp/test/mac/copies-with-xcode-envvars/file5 @@ -0,0 +1 @@ +file5 contents diff --git a/tools/gyp/test/mac/copies-with-xcode-envvars/file6 b/tools/gyp/test/mac/copies-with-xcode-envvars/file6 new file mode 100644 index 00000000000000..f5d57573486772 --- /dev/null +++ b/tools/gyp/test/mac/copies-with-xcode-envvars/file6 @@ -0,0 +1 @@ +file6 contents diff --git a/tools/gyp/test/mac/copies-with-xcode-envvars/file7 b/tools/gyp/test/mac/copies-with-xcode-envvars/file7 new file mode 100644 index 00000000000000..90dbe6e9e1123b --- /dev/null +++ b/tools/gyp/test/mac/copies-with-xcode-envvars/file7 @@ -0,0 +1 @@ +file7 contents diff --git a/tools/gyp/test/mac/copies-with-xcode-envvars/file8 b/tools/gyp/test/mac/copies-with-xcode-envvars/file8 new file mode 100644 index 00000000000000..9eb613fabbf7ec --- /dev/null +++ b/tools/gyp/test/mac/copies-with-xcode-envvars/file8 @@ -0,0 +1 @@ +file8 contents diff --git a/tools/gyp/test/mac/copies-with-xcode-envvars/file9 b/tools/gyp/test/mac/copies-with-xcode-envvars/file9 new file mode 100644 index 00000000000000..e37ac72adab0db --- /dev/null +++ b/tools/gyp/test/mac/copies-with-xcode-envvars/file9 @@ -0,0 +1 @@ +file9 contents diff --git a/tools/gyp/test/mac/copy-dylib/empty.c b/tools/gyp/test/mac/copy-dylib/empty.c new file mode 100644 index 00000000000000..237c8ce181774d --- /dev/null +++ b/tools/gyp/test/mac/copy-dylib/empty.c @@ -0,0 +1 @@ +int main() {} diff --git a/tools/gyp/test/mac/copy-dylib/test.gyp b/tools/gyp/test/mac/copy-dylib/test.gyp new file mode 100644 index 00000000000000..4210c51463453e --- /dev/null +++ b/tools/gyp/test/mac/copy-dylib/test.gyp @@ -0,0 +1,31 @@ +# 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': 'my_dylib', + 'type': 'shared_library', + 'sources': [ 'empty.c', ], + }, + { + 'target_name': 'test_app', + 'product_name': 'Test App', + 'type': 'executable', + 'mac_bundle': 1, + 'dependencies': [ 'my_dylib', ], + 'sources': [ + 'empty.c', + ], + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/Test App.app/Contents/Resources', + 'files': [ + '<(PRODUCT_DIR)/libmy_dylib.dylib', + ], + }, + ], + }, + ], +} + diff --git a/tools/gyp/test/mac/debuginfo/file.c b/tools/gyp/test/mac/debuginfo/file.c new file mode 100644 index 00000000000000..9cddaf1b0b401b --- /dev/null +++ b/tools/gyp/test/mac/debuginfo/file.c @@ -0,0 +1,6 @@ +// 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. + +void f() {} +int main() {} diff --git a/tools/gyp/test/mac/debuginfo/test.gyp b/tools/gyp/test/mac/debuginfo/test.gyp new file mode 100644 index 00000000000000..3faf6b5c76edf3 --- /dev/null +++ b/tools/gyp/test/mac/debuginfo/test.gyp @@ -0,0 +1,82 @@ +# 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': 'nonbundle_static_library', + 'type': 'static_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + { + 'target_name': 'nonbundle_shared_library', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + { + 'target_name': 'nonbundle_loadable_module', + 'type': 'loadable_module', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + { + 'target_name': 'nonbundle_executable', + 'type': 'executable', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + + { + 'target_name': 'bundle_shared_library', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + { + 'target_name': 'bundle_loadable_module', + 'type': 'loadable_module', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + { + 'target_name': 'my_app', + 'product_name': 'My App', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/depend-on-bundle/English.lproj/InfoPlist.strings b/tools/gyp/test/mac/depend-on-bundle/English.lproj/InfoPlist.strings new file mode 100644 index 00000000000000..b92732c79e00cf --- /dev/null +++ b/tools/gyp/test/mac/depend-on-bundle/English.lproj/InfoPlist.strings @@ -0,0 +1 @@ +/* Localized versions of Info.plist keys */ diff --git a/tools/gyp/test/mac/depend-on-bundle/Info.plist b/tools/gyp/test/mac/depend-on-bundle/Info.plist new file mode 100644 index 00000000000000..5e05a5190c8931 --- /dev/null +++ b/tools/gyp/test/mac/depend-on-bundle/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.yourcompany.${PRODUCT_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSPrincipalClass + + + diff --git a/tools/gyp/test/mac/depend-on-bundle/bundle.c b/tools/gyp/test/mac/depend-on-bundle/bundle.c new file mode 100644 index 00000000000000..d64ff8ca23dbf9 --- /dev/null +++ b/tools/gyp/test/mac/depend-on-bundle/bundle.c @@ -0,0 +1 @@ +int f() { return 42; } diff --git a/tools/gyp/test/mac/depend-on-bundle/executable.c b/tools/gyp/test/mac/depend-on-bundle/executable.c new file mode 100644 index 00000000000000..931bce637edaa2 --- /dev/null +++ b/tools/gyp/test/mac/depend-on-bundle/executable.c @@ -0,0 +1,4 @@ +int f(); +int main() { + return f(); +} diff --git a/tools/gyp/test/mac/depend-on-bundle/test.gyp b/tools/gyp/test/mac/depend-on-bundle/test.gyp new file mode 100644 index 00000000000000..e00b1054159331 --- /dev/null +++ b/tools/gyp/test/mac/depend-on-bundle/test.gyp @@ -0,0 +1,28 @@ +# 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': 'my_bundle', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'bundle.c' ], + 'mac_bundle_resources': [ + 'English.lproj/InfoPlist.strings', + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + } + }, + { + 'target_name': 'dependent_on_bundle', + 'type': 'executable', + 'sources': [ 'executable.c' ], + 'dependencies': [ + 'my_bundle', + ], + }, + ], +} + diff --git a/tools/gyp/test/mac/deployment-target/check-version-min.c b/tools/gyp/test/mac/deployment-target/check-version-min.c new file mode 100644 index 00000000000000..761c529085d52a --- /dev/null +++ b/tools/gyp/test/mac/deployment-target/check-version-min.c @@ -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. */ + +#include + +/* GYPTEST_MAC_VERSION_MIN: should be set to the corresponding value of + * xcode setting 'MACOSX_DEPLOYMENT_TARGET', otherwise both should be + * left undefined. + * + * GYPTEST_IOS_VERSION_MIN: should be set to the corresponding value of + * xcode setting 'IPHONEOS_DEPLOYMENT_TARGET', otherwise both should be + * left undefined. + */ + +#if defined(GYPTEST_MAC_VERSION_MIN) +# if GYPTEST_MAC_VERSION_MIN != __MAC_OS_X_VERSION_MIN_REQUIRED +# error __MAC_OS_X_VERSION_MIN_REQUIRED has wrong value +# endif +#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +# error __MAC_OS_X_VERSION_MIN_REQUIRED should be undefined +#endif + +#if defined(GYPTEST_IOS_VERSION_MIN) +# if GYPTEST_IOS_VERSION_MIN != __IPHONE_OS_VERSION_MIN_REQUIRED +# error __IPHONE_OS_VERSION_MIN_REQUIRED has wrong value +# endif +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +# error __IPHONE_OS_VERSION_MIN_REQUIRED should be undefined +#endif + +int main() { return 0; } + diff --git a/tools/gyp/test/mac/deployment-target/deployment-target.gyp b/tools/gyp/test/mac/deployment-target/deployment-target.gyp new file mode 100644 index 00000000000000..47e0565c0c7d62 --- /dev/null +++ b/tools/gyp/test/mac/deployment-target/deployment-target.gyp @@ -0,0 +1,28 @@ +# 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': 'macosx-version-min-10.5', + 'type': 'executable', + 'sources': [ 'check-version-min.c', ], + 'defines': [ 'GYPTEST_MAC_VERSION_MIN=1050', ], + 'xcode_settings': { + 'SDKROOT': 'macosx', + 'MACOSX_DEPLOYMENT_TARGET': '10.5', + }, + }, + { + 'target_name': 'macosx-version-min-10.6', + 'type': 'executable', + 'sources': [ 'check-version-min.c', ], + 'defines': [ 'GYPTEST_MAC_VERSION_MIN=1060', ], + 'xcode_settings': { + 'SDKROOT': 'macosx', + 'MACOSX_DEPLOYMENT_TARGET': '10.6', + }, + }, + ], +} + diff --git a/tools/gyp/test/mac/framework-dirs/calculate.c b/tools/gyp/test/mac/framework-dirs/calculate.c new file mode 100644 index 00000000000000..7dc9d2d8b46f85 --- /dev/null +++ b/tools/gyp/test/mac/framework-dirs/calculate.c @@ -0,0 +1,15 @@ +/* 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. + */ + +int CalculatePerformExpression(char* expr, + int significantDigits, + int flags, + char* answer); + +int main() { + char buffer[1024]; + return CalculatePerformExpression("42", 1, 0, buffer); +} + diff --git a/tools/gyp/test/mac/framework-dirs/framework-dirs.gyp b/tools/gyp/test/mac/framework-dirs/framework-dirs.gyp new file mode 100644 index 00000000000000..bf1cbde4defc5a --- /dev/null +++ b/tools/gyp/test/mac/framework-dirs/framework-dirs.gyp @@ -0,0 +1,21 @@ +# 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': 'calculate', + 'type': 'executable', + 'sources': [ + 'calculate.c', + ], + 'libraries': [ + '/System/Library/PrivateFrameworks/Calculate.framework', + ], + 'mac_framework_dirs': [ + '/System/Library/PrivateFrameworks', + ], + }, + ], +} diff --git a/tools/gyp/test/mac/framework-headers/myframework.h b/tools/gyp/test/mac/framework-headers/myframework.h new file mode 100644 index 00000000000000..961fc701bc0b51 --- /dev/null +++ b/tools/gyp/test/mac/framework-headers/myframework.h @@ -0,0 +1,8 @@ +// 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. + +#import + +@interface TestObject : NSObject +@end diff --git a/tools/gyp/test/mac/framework-headers/myframework.m b/tools/gyp/test/mac/framework-headers/myframework.m new file mode 100644 index 00000000000000..13d53a37ab716d --- /dev/null +++ b/tools/gyp/test/mac/framework-headers/myframework.m @@ -0,0 +1,8 @@ +// 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. + +#import "myframework.h" + +@implementation TestObject +@end diff --git a/tools/gyp/test/mac/framework-headers/test.gyp b/tools/gyp/test/mac/framework-headers/test.gyp new file mode 100644 index 00000000000000..70ed00715c8ffc --- /dev/null +++ b/tools/gyp/test/mac/framework-headers/test.gyp @@ -0,0 +1,44 @@ +# 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': 'test_framework_headers_framework', + 'product_name': 'TestFramework', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ + 'myframework.h', + 'myframework.m', + ], + 'mac_framework_headers': [ + 'myframework.h', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + ], + }, + },{ + 'target_name': 'test_framework_headers_static', + 'product_name': 'TestLibrary', + 'type': 'static_library', + 'xcode_settings': { + 'PUBLIC_HEADERS_FOLDER_PATH': 'include', + }, + 'sources': [ + 'myframework.h', + 'myframework.m', + ], + 'mac_framework_headers': [ + 'myframework.h', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + ], + }, + }, + ], +} diff --git a/tools/gyp/test/mac/framework/TestFramework/English.lproj/InfoPlist.strings b/tools/gyp/test/mac/framework/TestFramework/English.lproj/InfoPlist.strings new file mode 100644 index 00000000000000..88f65cf6eab17b --- /dev/null +++ b/tools/gyp/test/mac/framework/TestFramework/English.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/tools/gyp/test/mac/framework/TestFramework/Info.plist b/tools/gyp/test/mac/framework/TestFramework/Info.plist new file mode 100644 index 00000000000000..a791b3ee48d1e6 --- /dev/null +++ b/tools/gyp/test/mac/framework/TestFramework/Info.plist @@ -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 --git a/tools/gyp/test/mac/framework/TestFramework/ObjCVector.h b/tools/gyp/test/mac/framework/TestFramework/ObjCVector.h new file mode 100644 index 00000000000000..c2450960cd24c8 --- /dev/null +++ b/tools/gyp/test/mac/framework/TestFramework/ObjCVector.h @@ -0,0 +1,28 @@ +// 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. + +#import + +#ifdef __cplusplus +struct ObjCVectorImp; +#else +typedef struct _ObjCVectorImpT ObjCVectorImp; +#endif + +@interface ObjCVector : NSObject { + @private + ObjCVectorImp* imp_; +} + +- (id)init; + +- (void)addObject:(id)obj; +- (void)addObject:(id)obj atIndex:(NSUInteger)index; + +- (void)removeObject:(id)obj; +- (void)removeObjectAtIndex:(NSUInteger)index; + +- (id)objectAtIndex:(NSUInteger)index; + +@end diff --git a/tools/gyp/test/mac/framework/TestFramework/ObjCVector.mm b/tools/gyp/test/mac/framework/TestFramework/ObjCVector.mm new file mode 100644 index 00000000000000..cbf431f28d4d9d --- /dev/null +++ b/tools/gyp/test/mac/framework/TestFramework/ObjCVector.mm @@ -0,0 +1,63 @@ +// 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. + +#import "ObjCVectorInternal.h" +#import "ObjCVector.h" + +#include + +@interface ObjCVector (Private) +- (std::vector::iterator)makeIterator:(NSUInteger)index; +@end + +@implementation ObjCVector + +- (id)init { + if ((self = [super init])) { + imp_ = new ObjCVectorImp(); + } + return self; +} + +- (void)dealloc { + delete imp_; + [super dealloc]; +} + +- (void)addObject:(id)obj { + imp_->v.push_back([obj retain]); +} + +- (void)addObject:(id)obj atIndex:(NSUInteger)index { + imp_->v.insert([self makeIterator:index], [obj retain]); +} + +- (void)removeObject:(id)obj { + for (std::vector::iterator it = imp_->v.begin(); + it != imp_->v.end(); + ++it) { + if ([*it isEqual:obj]) { + [*it autorelease]; + imp_->v.erase(it); + return; + } + } +} + +- (void)removeObjectAtIndex:(NSUInteger)index { + [imp_->v[index] autorelease]; + imp_->v.erase([self makeIterator:index]); +} + +- (id)objectAtIndex:(NSUInteger)index { + return imp_->v[index]; +} + +- (std::vector::iterator)makeIterator:(NSUInteger)index { + std::vector::iterator it = imp_->v.begin(); + it += index; + return it; +} + +@end diff --git a/tools/gyp/test/mac/framework/TestFramework/ObjCVectorInternal.h b/tools/gyp/test/mac/framework/TestFramework/ObjCVectorInternal.h new file mode 100644 index 00000000000000..fb6c98258b5e2b --- /dev/null +++ b/tools/gyp/test/mac/framework/TestFramework/ObjCVectorInternal.h @@ -0,0 +1,9 @@ +// 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. + +#include + +struct ObjCVectorImp { + std::vector v; +}; diff --git a/tools/gyp/test/mac/framework/TestFramework/TestFramework_Prefix.pch b/tools/gyp/test/mac/framework/TestFramework/TestFramework_Prefix.pch new file mode 100644 index 00000000000000..394f41d9576a62 --- /dev/null +++ b/tools/gyp/test/mac/framework/TestFramework/TestFramework_Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'TestFramework' target in the 'TestFramework' project. +// + +#ifdef __OBJC__ + #import +#endif diff --git a/tools/gyp/test/mac/framework/empty.c b/tools/gyp/test/mac/framework/empty.c new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/mac/framework/framework.gyp b/tools/gyp/test/mac/framework/framework.gyp new file mode 100644 index 00000000000000..52b4f37be93ed7 --- /dev/null +++ b/tools/gyp/test/mac/framework/framework.gyp @@ -0,0 +1,108 @@ +# 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 Bundle', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'empty.c', ], + }, + { + 'target_name': 'test_framework', + 'product_name': 'Test Framework', + 'type': 'shared_library', + 'mac_bundle': 1, + 'dependencies': [ 'dep_framework', ], + 'sources': [ + 'TestFramework/ObjCVector.h', + 'TestFramework/ObjCVectorInternal.h', + 'TestFramework/ObjCVector.mm', + ], + 'mac_bundle_resources': [ + 'TestFramework/English.lproj/InfoPlist.strings', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Cocoa.framework', + ], + }, + 'xcode_settings': { + 'INFOPLIST_FILE': 'TestFramework/Info.plist', + 'GCC_DYNAMIC_NO_PIC': 'NO', + }, + 'copies': [ + # Test copying to a file that has envvars in its dest path. + # Needs to be in a mac_bundle target, else CONTENTS_FOLDER_PATH isn't + # set. + { + 'destination': '<(PRODUCT_DIR)/$(CONTENTS_FOLDER_PATH)/Libraries', + 'files': [ + 'empty.c', + ], + }, + ], + }, + { + 'target_name': 'copy_target', + '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', + ], + }, + ], + 'actions': [ + { + 'action_name': 'aektschn', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/touched_file'], + 'action': ['touch', '${BUILT_PRODUCTS_DIR}/action_file'], + }, + ], + }, + { + 'target_name': 'copy_embedded', + 'type': 'none', + 'dependencies': [ 'test_framework' ], + 'copies': [ + # Test copying framework to FRAMEWORK directory. + { + 'destination': '$(BUILT_FRAMEWORKS_DIR)/Embedded', + 'files': [ + '<(PRODUCT_DIR)/Test Framework.framework', + ], + }, + ], + }, + { + '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 --git a/tools/gyp/test/mac/global-settings/src/dir1/dir1.gyp b/tools/gyp/test/mac/global-settings/src/dir1/dir1.gyp new file mode 100644 index 00000000000000..153e34ddd681ca --- /dev/null +++ b/tools/gyp/test/mac/global-settings/src/dir1/dir1.gyp @@ -0,0 +1,11 @@ +# 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': 'dir1_target', + 'type': 'none', + }, + ], +} diff --git a/tools/gyp/test/mac/global-settings/src/dir2/dir2.gyp b/tools/gyp/test/mac/global-settings/src/dir2/dir2.gyp new file mode 100644 index 00000000000000..cda46c839badec --- /dev/null +++ b/tools/gyp/test/mac/global-settings/src/dir2/dir2.gyp @@ -0,0 +1,22 @@ +# 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': 'dir2_target', + 'type': 'none', + 'dependencies': [ + '../dir1/dir1.gyp:dir1_target', + ], + 'actions': [ + { + 'inputs': [ ], + 'outputs': [ '<(PRODUCT_DIR)/file.txt' ], + 'action_name': 'Test action', + 'action': ['cp', 'file.txt', '${BUILT_PRODUCTS_DIR}/file.txt' ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/mac/global-settings/src/dir2/file.txt b/tools/gyp/test/mac/global-settings/src/dir2/file.txt new file mode 100644 index 00000000000000..58da2d8e9acf40 --- /dev/null +++ b/tools/gyp/test/mac/global-settings/src/dir2/file.txt @@ -0,0 +1 @@ +File. diff --git a/tools/gyp/test/mac/gyptest-action-envvars.py b/tools/gyp/test/mac/gyptest-action-envvars.py new file mode 100644 index 00000000000000..c84eeaa465ab0e --- /dev/null +++ b/tools/gyp/test/mac/gyptest-action-envvars.py @@ -0,0 +1,36 @@ +#!/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 env vars work with actions, with relative directory paths. +""" + +import TestGyp + +import sys + +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') + + result_file = test.built_file_path('result', chdir=CHDIR) + test.must_exist(result_file) + test.must_contain(result_file, 'Test output') + + other_result_file = test.built_file_path('other_result', chdir=CHDIR) + test.must_exist(other_result_file) + test.must_contain(other_result_file, 'Other output') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-app-assets-catalog.py b/tools/gyp/test/mac/gyptest-app-assets-catalog.py new file mode 100644 index 00000000000000..7a215e934e6117 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-app-assets-catalog.py @@ -0,0 +1,101 @@ +#!/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. +""" + +from __future__ import print_function + +import os +import plistlib +import subprocess + +import TestGyp +from XCodeDetect import XCodeDetect + +test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], platforms=['darwin'], disable="This test is currently disabled: https://crbug.com/483696.") + +def ExpectEq(expct, actual): + if expct != actual: + test.fail_test(message='Expected "%s", got "%s"' % (expct, actual)) + + +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 XCodeDetect.Version() < '0600': + test.skip_test('Skip test on XCode < 0600') + +test_gyp_path = 'test-assets-catalog.gyp' +test_app_path = 'Test App Assets Catalog Gyp.app' + +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']).strip() + plist = plistlib.readPlist(info_plist) + ExpectEq(machine, plist['BuildMachineOSBuild']) + + expected = 'macosx' + XCodeDetect.SDKVersion() + ExpectEq(expected, plist['DTSDKName']) + ExpectEq(XCodeDetect.Version(), plist['DTXcode']) + +# 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. +expected_files = 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] +) +if set(ls(test.built_file_path(test_app_path, chdir='app-bundle'))) != expected_files: + test.fail_test() + +test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-app-error.py b/tools/gyp/test/mac/gyptest-app-error.py new file mode 100644 index 00000000000000..9f918c536f25a2 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-app-error.py @@ -0,0 +1,56 @@ +#!/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 invalid strings files cause the build to fail. +""" + +from __future__ import print_function + +import sys + +if sys.platform == 'darwin': + print("This test is currently disabled: https://crbug.com/483696.") + sys.exit(0) + +if sys.platform != 'darwin': + print("Only for macOS") + sys.exit(2) + +from SConsLib import TestCmd +import TestGyp + +expected_error = 'Old-style plist parser: missing semicolon in dictionary' +saw_expected_error = [False] # Python2 has no "nonlocal" keyword. + + +def match(a, b): + if a == b: + return True + if not TestCmd.is_List(a): + a = a.split('\n') + if not TestCmd.is_List(b): + b = b.split('\n') + if expected_error in '\n'.join(a) + '\n'.join(b): + saw_expected_error[0] = True + return True + return False + + +test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], match=match) + +test.run_gyp('test-error.gyp', chdir='app-bundle') + +test.build('test-error.gyp', test.ALL, chdir='app-bundle') + +# Ninja pipes stderr of subprocesses to stdout. +if test.format in ['ninja', 'xcode-ninja'] and expected_error in test.stdout(): + saw_expected_error[0] = True + +if saw_expected_error[0]: + test.pass_test() +else: + test.fail_test() diff --git a/tools/gyp/test/mac/gyptest-app.py b/tools/gyp/test/mac/gyptest-app.py new file mode 100644 index 00000000000000..1351bca8e73811 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-app.py @@ -0,0 +1,108 @@ +#!/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. +""" + +from __future__ import print_function + +import os +import plistlib +import subprocess +import sys + +import TestGyp +from XCodeDetect import XCodeDetect + +test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], platforms=['darwin'], disable="This test is currently disabled: https://crbug.com/483696.") + + +# noinspection PyUnreachableCode +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('Expected "%s", got "%s"' % (expected, actual), file=sys.stderr) + 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 + + +test.run_gyp('test.gyp', chdir='app-bundle') + +test.build('test.gyp', test.ALL, chdir='app-bundle') + +# Binary +test.built_file_must_exist('Test App Gyp.app/Contents/MacOS/Test App Gyp', chdir='app-bundle') + +# Info.plist +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_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 XCodeDetect.Version() >= '0500': + version = XCodeDetect.SDKVersion() + expected = 'macosx' + version + ExpectEq(expected, plist['DTSDKName']) + ExpectEq(XCodeDetect.Version(), plist['DTXcode']) + +# 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 Gyp.app/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('Test App Gyp.app/Contents/Resources/English.lproj/MainMenu.nib', chdir='app-bundle') + +# Packaging +test.built_file_must_exist('Test App Gyp.app/Contents/PkgInfo', chdir='app-bundle') +test.built_file_must_match('Test App Gyp.app/Contents/PkgInfo', 'APPLause', chdir='app-bundle') + +# Check that no other files get added to the bundle. +expected_file_set = set( + [ + 'Contents/MacOS/Test App Gyp', + 'Contents/Info.plist', + 'Contents/Resources/English.lproj/MainMenu.nib', + 'Contents/PkgInfo', + ] + [os.path.join('Contents/Resources/English.lproj', f) for f in strings_files] +) +if set(ls(test.built_file_path('Test App Gyp.app', chdir='app-bundle'))) != expected_file_set: + test.fail_test() + +test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-archs.py b/tools/gyp/test/mac/gyptest-archs.py new file mode 100644 index 00000000000000..3bbd68fc137a33 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-archs.py @@ -0,0 +1,93 @@ +#!/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. + +""" +Tests things related to ARCHS. +""" + +import subprocess + +import TestGyp +import XCodeDetect + +test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], platforms=['darwin']) + +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) + +if XCodeDetect.XCodeDetect.Version() >= '0500': + expected_type = ['x86_64'] +else: + expected_type = ['i386'] +TestGyp.CheckFileType_macOS(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) +TestGyp.CheckFileType_macOS(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) +TestGyp.CheckFileType_macOS(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) + +# The rest is XCode / ninja only +if test.format == 'make': + test.pass_test() + +# 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') + +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) +TestGyp.CheckFileType_macOS(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) +TestGyp.CheckFileType_macOS(test, result_file, ['i386', 'x86_64']) + +result_file = test.built_file_path('My Framework.framework/My Framework', + chdir='archs') +test.must_exist(result_file) +TestGyp.CheckFileType_macOS(test, result_file, ['i386', 'x86_64']) +# Check that symbol "_x" made it into both versions of the binary: +for arch in ['i386', 'x86_64']: + out = subprocess.check_output(['nm', '-arch', arch, result_file]).decode('utf-8') + if not 'D _x' in out: + # 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) +TestGyp.CheckFileType_macOS(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) +TestGyp.CheckFileType_macOS(test, result_file, ['i386', 'x86_64']) diff --git a/tools/gyp/test/mac/gyptest-bundle-resources.py b/tools/gyp/test/mac/gyptest-bundle-resources.py new file mode 100644 index 00000000000000..7938a375573b3b --- /dev/null +++ b/tools/gyp/test/mac/gyptest-bundle-resources.py @@ -0,0 +1,63 @@ +#!/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 things related to bundle resources. +""" + +from __future__ import print_function + +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']) + + CHDIR = 'bundle-resources' + test.run_gyp('test.gyp', chdir=CHDIR) + + test.build('test.gyp', test.ALL, chdir=CHDIR) + + test.built_file_must_match('resource.app/Contents/Resources/secret.txt', + 'abc\n', chdir=CHDIR) + 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( + 'resource_rule.app/Contents/Resources/secret.txt', 'ABC\n', chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-cflags.py b/tools/gyp/test/mac/gyptest-cflags.py new file mode 100644 index 00000000000000..17afd1566542c0 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-cflags.py @@ -0,0 +1,21 @@ +#!/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 compile-time flags work. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + 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 --git a/tools/gyp/test/mac/gyptest-clang-cxx-language-standard.py b/tools/gyp/test/mac/gyptest-clang-cxx-language-standard.py new file mode 100644 index 00000000000000..75c6c74c97fc77 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-clang-cxx-language-standard.py @@ -0,0 +1,25 @@ +#!/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 CLANG_CXX_LANGUAGE_STANDARD works. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['make', 'ninja', 'xcode']) + + test.run_gyp('clang-cxx-language-standard.gyp', + chdir='clang-cxx-language-standard') + + test.build('clang-cxx-language-standard.gyp', test.ALL, + chdir='clang-cxx-language-standard') + + test.pass_test() + diff --git a/tools/gyp/test/mac/gyptest-clang-cxx-library.py b/tools/gyp/test/mac/gyptest-clang-cxx-library.py new file mode 100644 index 00000000000000..2c4b0d8f9f8dd9 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-clang-cxx-library.py @@ -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. + +""" +Verifies that CLANG_CXX_LIBRARY works. +""" + +import TestGyp +import XCodeDetect + +test = TestGyp.TestGyp(formats=['make', 'ninja', 'xcode'], platforms=['darwin']) +# Xcode 4.2 on OS X 10.6 doesn't install the libc++ headers, don't run this test there. +if XCodeDetect.XCodeDetect.Version() <= '0420': + test.skip_test('test only on XCode > 0420') + +if test.format == 'make': + # This is failing because of a deprecation warning for libstdc++. + test.skip_test() # bug=533 + +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 --git a/tools/gyp/test/mac/gyptest-copies-with-xcode-envvars.py b/tools/gyp/test/mac/gyptest-copies-with-xcode-envvars.py new file mode 100644 index 00000000000000..f5b5be20b9e41c --- /dev/null +++ b/tools/gyp/test/mac/gyptest-copies-with-xcode-envvars.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python + +# Copyright (c) 2016 Mark Callow. 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 files are copied to the correct destinations when those +destinations are specified using environment variables available in +Xcode's PBXCopyFilesBuildPhase. +""" + +import TestGyp + +import os +import stat +import sys + + +test = TestGyp.TestGyp(formats=['make', 'ninja', 'xcode']) + +if sys.platform == 'darwin': + test.run_gyp('copies-with-xcode-envvars.gyp', + chdir='copies-with-xcode-envvars') + + test.build('copies-with-xcode-envvars.gyp', chdir='copies-with-xcode-envvars') + + wrapper_name = 'copies-with-xcode-envvars.app/' + contents_path = wrapper_name + 'Contents/' + out_path = test.built_file_path('file0', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file0 contents\n') + out_path = test.built_file_path(wrapper_name + 'file1', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file1 contents\n') + out_path = test.built_file_path(contents_path + 'MacOS/file2', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file2 contents\n') + out_path = test.built_file_path(contents_path + 'Resources/file3', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file3 contents\n') + out_path = test.built_file_path(contents_path + 'Resources/testimages/file4', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file4 contents\n') + out_path = test.built_file_path(contents_path + 'Resources/Java/file5', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file5 contents\n') + out_path = test.built_file_path(contents_path + 'Frameworks/file6', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file6 contents\n') + out_path = test.built_file_path(contents_path + 'Frameworks/file7', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file7 contents\n') + out_path = test.built_file_path(contents_path + 'SharedFrameworks/file8', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file8 contents\n') + out_path = test.built_file_path(contents_path + 'SharedSupport/file9', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file9 contents\n') + out_path = test.built_file_path(contents_path + 'PlugIns/file10', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file10 contents\n') + out_path = test.built_file_path(contents_path + 'XPCServices/file11', chdir='copies-with-xcode-envvars') + test.must_contain(out_path, 'file11 contents\n') + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-copies.py b/tools/gyp/test/mac/gyptest-copies.py new file mode 100644 index 00000000000000..668b9fa040b5f7 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-copies.py @@ -0,0 +1,61 @@ +#!/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 'copies' with app bundles are handled correctly. +""" + +from __future__ import print_function + +import TestGyp + +import os +import sys +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') + + test.build('framework.gyp', 'copy_target', chdir='framework') + + # Check that the copy succeeded. + test.built_file_must_exist( + 'Test Framework.framework/foo/Dependency Bundle.framework', + chdir='framework') + test.built_file_must_exist( + 'Test Framework.framework/foo/Dependency Bundle.framework/Versions/A', + chdir='framework') + test.built_file_must_exist( + 'Test Framework.framework/Versions/A/Libraries/empty.c', + chdir='framework') + + # Verify BUILT_FRAMEWORKS_DIR is set and working. + test.build('framework.gyp', 'copy_embedded', chdir='framework') + + test.built_file_must_exist( + 'Embedded/Test Framework.framework', chdir='framework') + + # Check that rebuilding the target a few times works. + dep_bundle = test.built_file_path('Dependency Bundle.framework', chdir='framework') + mtime = os.path.getmtime(dep_bundle) + atime = os.path.getatime(dep_bundle) + for i in range(3): + os.utime(dep_bundle, (atime + i * 1000, mtime + i * 1000)) + test.build('framework.gyp', 'copy_target', chdir='framework') + + + # 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 --git a/tools/gyp/test/mac/gyptest-copy-dylib.py b/tools/gyp/test/mac/gyptest-copy-dylib.py new file mode 100644 index 00000000000000..253623d1c69dfa --- /dev/null +++ b/tools/gyp/test/mac/gyptest-copy-dylib.py @@ -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. + +""" +Verifies that dylibs can be copied into app bundles. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + + test.run_gyp('test.gyp', chdir='copy-dylib') + + test.build('test.gyp', 'test_app', chdir='copy-dylib') + + test.built_file_must_exist( + 'Test App.app/Contents/Resources/libmy_dylib.dylib', chdir='copy-dylib') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-debuginfo.py b/tools/gyp/test/mac/gyptest-debuginfo.py new file mode 100644 index 00000000000000..a0e9438e2a6bfd --- /dev/null +++ b/tools/gyp/test/mac/gyptest-debuginfo.py @@ -0,0 +1,36 @@ +#!/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. + +""" +Tests things related to debug information generation. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + + test.run_gyp('test.gyp', chdir='debuginfo') + + test.build('test.gyp', test.ALL, chdir='debuginfo') + + test.built_file_must_exist('libnonbundle_shared_library.dylib.dSYM', + chdir='debuginfo') + test.built_file_must_exist('nonbundle_loadable_module.so.dSYM', + chdir='debuginfo') + test.built_file_must_exist('nonbundle_executable.dSYM', + chdir='debuginfo') + + test.built_file_must_exist('bundle_shared_library.framework.dSYM', + chdir='debuginfo') + test.built_file_must_exist('bundle_loadable_module.bundle.dSYM', + chdir='debuginfo') + test.built_file_must_exist('My App.app.dSYM', + chdir='debuginfo') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-depend-on-bundle.py b/tools/gyp/test/mac/gyptest-depend-on-bundle.py new file mode 100644 index 00000000000000..b8b06d4cc00985 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-depend-on-bundle.py @@ -0,0 +1,45 @@ +#!/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 a dependency on a bundle causes the whole bundle to be built. +""" + +from __future__ import print_function + +import TestGyp + +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') + + test.build('test.gyp', 'dependent_on_bundle', chdir='depend-on-bundle') + + # Binary itself. + test.built_file_must_exist('dependent_on_bundle', chdir='depend-on-bundle') + + # Bundle dependency. + test.built_file_must_exist( + 'my_bundle.framework/Versions/A/my_bundle', + chdir='depend-on-bundle') + test.built_file_must_exist( # package_framework + 'my_bundle.framework/my_bundle', + chdir='depend-on-bundle') + test.built_file_must_exist( # plist + 'my_bundle.framework/Versions/A/Resources/Info.plist', + chdir='depend-on-bundle') + test.built_file_must_exist( + 'my_bundle.framework/Versions/A/Resources/English.lproj/' # Resources + 'InfoPlist.strings', + chdir='depend-on-bundle') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-deployment-target.py b/tools/gyp/test/mac/gyptest-deployment-target.py new file mode 100644 index 00000000000000..c7eabde6fe0298 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-deployment-target.py @@ -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. + +""" +Verifies that MACOSX_DEPLOYMENT_TARGET works. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['make', 'ninja', 'xcode']) + + if test.format == 'make': + # This is failing because of a deprecation warning for libstdc++. + test.skip_test() # bug=533 + + test.run_gyp('deployment-target.gyp', chdir='deployment-target') + + test.build('deployment-target.gyp', test.ALL, chdir='deployment-target') + + test.pass_test() + diff --git a/tools/gyp/test/mac/gyptest-framework-dirs.py b/tools/gyp/test/mac/gyptest-framework-dirs.py new file mode 100644 index 00000000000000..a1ae54c57fbeb0 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-framework-dirs.py @@ -0,0 +1,23 @@ +#!/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 it is possible to build an object that depends on a +PrivateFramework. +""" + +import os +import sys +import TestGyp + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + + CHDIR = 'framework-dirs' + test.run_gyp('framework-dirs.gyp', chdir=CHDIR) + test.build('framework-dirs.gyp', 'calculate', chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-framework-headers.py b/tools/gyp/test/mac/gyptest-framework-headers.py new file mode 100644 index 00000000000000..aa13a742cdd3a6 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-framework-headers.py @@ -0,0 +1,38 @@ +#!/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 mac_framework_headers works properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + # TODO(thakis): Make this work with ninja, make. http://crbug.com/129013 + test = TestGyp.TestGyp(formats=['xcode']) + + CHDIR = 'framework-headers' + test.run_gyp('test.gyp', chdir=CHDIR) + + # Test that headers are installed for frameworks + test.build('test.gyp', 'test_framework_headers_framework', chdir=CHDIR) + + test.built_file_must_exist( + 'TestFramework.framework/Versions/A/TestFramework', chdir=CHDIR) + + test.built_file_must_exist( + 'TestFramework.framework/Versions/A/Headers/myframework.h', chdir=CHDIR) + + # Test that headers are installed for static libraries. + test.build('test.gyp', 'test_framework_headers_static', chdir=CHDIR) + + test.built_file_must_exist('libTestLibrary.a', chdir=CHDIR) + + test.built_file_must_exist('include/myframework.h', chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-framework.py b/tools/gyp/test/mac/gyptest-framework.py new file mode 100644 index 00000000000000..0bc37351ae9cdf --- /dev/null +++ b/tools/gyp/test/mac/gyptest-framework.py @@ -0,0 +1,77 @@ +#!/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. +""" + +from __future__ import print_function + +import TestGyp + +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.''' + result = [] + for dirpath, _, files in os.walk(path): + for f in files: + result.append(os.path.join(dirpath, f)[len(path) + 1:]) + return result + + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + + test.run_gyp('framework.gyp', chdir='framework') + + test.build('framework.gyp', 'test_framework', chdir='framework') + + # Binary + test.built_file_must_exist( + 'Test Framework.framework/Versions/A/Test Framework', + chdir='framework') + + # Info.plist + 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( + 'Test Framework.framework/Versions/A/Resources/English.lproj/' + 'InfoPlist.strings', + chdir='framework') + + # Symlinks created by packaging process + test.built_file_must_exist('Test Framework.framework/Versions/Current', + chdir='framework') + test.built_file_must_exist('Test Framework.framework/Resources', + chdir='framework') + test.built_file_must_exist('Test Framework.framework/Test Framework', + chdir='framework') + # PkgInfo. + test.built_file_must_not_exist( + 'Test Framework.framework/Versions/A/Resources/PkgInfo', + chdir='framework') + + # Check that no other files get added to the bundle. + if set(ls(test.built_file_path('Test Framework.framework', chdir='framework'))) != \ + set(['Versions/A/Test Framework', + 'Versions/A/Resources/Info.plist', + 'Versions/A/Resources/English.lproj/InfoPlist.strings', + 'Test Framework', + 'Versions/A/Libraries/empty.c', # Written by a gyp action. + ]): + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-global-settings.py b/tools/gyp/test/mac/gyptest-global-settings.py new file mode 100644 index 00000000000000..f4ed16630e2f73 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-global-settings.py @@ -0,0 +1,33 @@ +#!/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 global xcode_settings processing doesn't throw. +Regression test for http://crbug.com/109163 +""" + +import TestGyp + +import sys + +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. + + # Check that BUILT_PRODUCTS_DIR was set correctly, too. + test.build('dir2/dir2.gyp', 'dir2_target', chdir='global-settings/src', + SYMROOT='../build') + test.built_file_must_exist('file.txt', chdir='global-settings/src') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-identical-name.py b/tools/gyp/test/mac/gyptest-identical-name.py new file mode 100644 index 00000000000000..a1b700f63466be --- /dev/null +++ b/tools/gyp/test/mac/gyptest-identical-name.py @@ -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 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 + +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 --git a/tools/gyp/test/mac/gyptest-infoplist-process.py b/tools/gyp/test/mac/gyptest-infoplist-process.py new file mode 100644 index 00000000000000..24260e1c34980f --- /dev/null +++ b/tools/gyp/test/mac/gyptest-infoplist-process.py @@ -0,0 +1,56 @@ +#!/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 the Info.plist preprocessor functionality. +""" + +from __future__ import print_function + +import TestGyp + +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' + INFO_PLIST_PATH = 'Test.app/Contents/Info.plist' + + # First process both keys. + test.set_configuration('One') + test.run_gyp('test1.gyp', chdir=CHDIR) + test.build('test1.gyp', test.ALL, chdir=CHDIR) + info_plist = test.built_file_path(INFO_PLIST_PATH, chdir=CHDIR) + test.must_exist(info_plist) + test.must_contain(info_plist, 'Foo') + test.must_contain(info_plist, 'Bar') + + # Then process a single key. + test.set_configuration('Two') + test.run_gyp('test2.gyp', chdir=CHDIR) + test.build('test2.gyp', chdir=CHDIR) + info_plist = test.built_file_path(INFO_PLIST_PATH, chdir=CHDIR) + test.must_exist(info_plist) + test.must_contain(info_plist, 'com.google.Test') # Normal expansion works. + test.must_contain(info_plist, 'Foo (Bar)') + test.must_contain(info_plist, 'PROCESSED_KEY2') + + # Then turn off the processor. + test.set_configuration('Three') + test.run_gyp('test3.gyp', chdir=CHDIR) + test.build('test3.gyp', chdir=CHDIR) + info_plist = test.built_file_path('Test App.app/Contents/Info.plist', + chdir=CHDIR) + test.must_exist(info_plist) + test.must_contain(info_plist, 'com.google.Test') # Normal expansion works. + test.must_contain(info_plist, 'PROCESSED_KEY1') + test.must_contain(info_plist, 'PROCESSED_KEY2') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-installname.py b/tools/gyp/test/mac/gyptest-installname.py new file mode 100644 index 00000000000000..17831aeaf432c6 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-installname.py @@ -0,0 +1,85 @@ +#!/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 LD_DYLIB_INSTALL_NAME and DYLIB_INSTALL_NAME_BASE are handled +correctly. +""" + +from __future__ import print_function + +import TestGyp + +import re +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 = 'installname' + test.run_gyp('test.gyp', chdir=CHDIR) + + test.build('test.gyp', test.ALL, chdir=CHDIR) + + def GetInstallname(p): + p = test.built_file_path(p, chdir=CHDIR) + r = re.compile(r'cmd LC_ID_DYLIB.*?name (.*?) \(offset \d+\)', re.DOTALL) + proc = subprocess.Popen(['otool', '-l', p], stdout=subprocess.PIPE) + o = proc.communicate()[0] + assert not proc.returncode + m = r.search(o) + assert m + return m.group(1) + + if (GetInstallname('libdefault_installname.dylib') != + '/usr/local/lib/libdefault_installname.dylib'): + test.fail_test() + + if (GetInstallname('My Framework.framework/My Framework') != + '/Library/Frameworks/My Framework.framework/' + 'Versions/A/My Framework'): + test.fail_test() + + if (GetInstallname('libexplicit_installname.dylib') != + 'Trapped in a dynamiclib factory'): + test.fail_test() + + if (GetInstallname('libexplicit_installname_base.dylib') != + '@executable_path/../../../libexplicit_installname_base.dylib'): + test.fail_test() + + if (GetInstallname('My Other Framework.framework/My Other Framework') != + '@executable_path/../../../My Other Framework.framework/' + 'Versions/A/My Other Framework'): + test.fail_test() + + if (GetInstallname('libexplicit_installname_with_base.dylib') != + '/usr/local/lib/libexplicit_installname_with_base.dylib'): + test.fail_test() + + if (GetInstallname('libexplicit_installname_with_explicit_base.dylib') != + '@executable_path/../libexplicit_installname_with_explicit_base.dylib'): + test.fail_test() + + if (GetInstallname('libboth_base_and_installname.dylib') != + 'Still trapped in a dynamiclib factory'): + test.fail_test() + + if (GetInstallname('install_name_with_info_plist.framework/' + 'install_name_with_info_plist') != + '/Library/Frameworks/install_name_with_info_plist.framework/' + 'Versions/A/install_name_with_info_plist'): + test.fail_test() + + if ('DYLIB_INSTALL_NAME_BASE:standardizepath: command not found' in + test.stdout()): + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-kext.py b/tools/gyp/test/mac/gyptest-kext.py new file mode 100644 index 00000000000000..db2291a7377637 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-kext.py @@ -0,0 +1,12 @@ +""" +Verifies that kext bundles are built correctly. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['xcode'], platforms=['darwin']) +test.run_gyp('kext.gyp', chdir='kext') +test.build('kext.gyp', test.ALL, chdir='kext') +test.built_file_must_exist('GypKext.kext/Contents/MacOS/GypKext', chdir='kext') +test.built_file_must_exist('GypKext.kext/Contents/Info.plist', chdir='kext') +test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-ldflags-passed-to-libtool.py b/tools/gyp/test/mac/gyptest-ldflags-passed-to-libtool.py new file mode 100644 index 00000000000000..e24e305d9fe535 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-ldflags-passed-to-libtool.py @@ -0,0 +1,37 @@ +#!/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 OTHER_LDFLAGS is passed to libtool. +""" + +from __future__ import print_function + +import TestGyp + +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) + + build_error_code = { + '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' + test.run_gyp('test.gyp', chdir=CHDIR) + + test.build('test.gyp', 'ldflags_passed_to_libtool', chdir=CHDIR, + status=build_error_code) + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-ldflags.py b/tools/gyp/test/mac/gyptest-ldflags.py new file mode 100644 index 00000000000000..af44b8c5a056a2 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-ldflags.py @@ -0,0 +1,74 @@ +#!/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 filenames passed to various linker flags are converted into +build-directory relative paths correctly. +""" + +import TestGyp + +import sys + +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) + + test.build('subdirectory/test.gyp', test.ALL, chdir=CHDIR) + + test.pass_test() + + +# These flags from `man ld` couldl show up in OTHER_LDFLAGS and need path +# translation. +# +# Done: +# -exported_symbols_list filename +# -unexported_symbols_list file +# -reexported_symbols_list file +# -sectcreate segname sectname file +# +# Will be done on demand: +# -weak_library path_to_library +# -reexport_library path_to_library +# -lazy_library path_to_library +# -upward_library path_to_library +# -syslibroot rootdir +# -framework name[,suffix] +# -weak_framework name[,suffix] +# -reexport_framework name[,suffix] +# -lazy_framework name[,suffix] +# -upward_framework name[,suffix] +# -force_load path_to_archive +# -filelist file[,dirname] +# -dtrace file +# -order_file file # should use ORDER_FILE +# -exported_symbols_order file +# -bundle_loader executable # should use BUNDLE_LOADER +# -alias_list filename +# -seg_addr_table filename +# -dylib_file install_name:file_name +# -interposable_list filename +# -object_path_lto filename +# +# +# obsolete: +# -sectorder segname sectname orderfile +# -seg_addr_table_filename path +# +# +# ??: +# -map map_file_path +# -sub_library library_name +# -sub_umbrella framework_name diff --git a/tools/gyp/test/mac/gyptest-libraries.py b/tools/gyp/test/mac/gyptest-libraries.py new file mode 100644 index 00000000000000..5ea4faf6eae4a6 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-libraries.py @@ -0,0 +1,30 @@ +#!/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 libraries (in link_settings) are properly found. +""" + +import TestGyp + +import sys + +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.skip_test() # bug=535 + + test.run_gyp('subdir/test.gyp', chdir='libraries') + + test.build('subdir/test.gyp', test.ALL, chdir='libraries') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-libtool-zero.py b/tools/gyp/test/mac/gyptest-libtool-zero.py new file mode 100644 index 00000000000000..ae5b7e635b5c1d --- /dev/null +++ b/tools/gyp/test/mac/gyptest-libtool-zero.py @@ -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 --git a/tools/gyp/test/mac/gyptest-loadable-module-bundle-product-extension.py b/tools/gyp/test/mac/gyptest-loadable-module-bundle-product-extension.py new file mode 100644 index 00000000000000..7a60ca2d177a01 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-loadable-module-bundle-product-extension.py @@ -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 --git a/tools/gyp/test/mac/gyptest-loadable-module.py b/tools/gyp/test/mac/gyptest-loadable-module.py new file mode 100644 index 00000000000000..0fcc5502b95034 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-loadable-module.py @@ -0,0 +1,51 @@ +#!/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. + +""" +Tests that a loadable_module target is built correctly. +""" + +from __future__ import print_function + +import TestGyp + +import os +import struct +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. + binary = test.built_file_path('test_loadable_module.plugin/Contents/MacOS/test_loadable_module', chdir=CHDIR) + test.must_exist(binary) + MH_BUNDLE = 8 + if struct.unpack('4I', open(binary, 'rb').read(16))[3] != MH_BUNDLE: + test.fail_test() + + # Info.plist. + info_plist = test.built_file_path('test_loadable_module.plugin/Contents/Info.plist', chdir=CHDIR) + test.must_exist(info_plist) + test.must_contain(info_plist, """ + CFBundleExecutable + test_loadable_module +""") + + # PkgInfo. + test.built_file_must_not_exist( + 'test_loadable_module.plugin/Contents/PkgInfo', chdir=CHDIR) + test.built_file_must_not_exist( + 'test_loadable_module.plugin/Contents/Resources', chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-lto.py b/tools/gyp/test/mac/gyptest-lto.py new file mode 100644 index 00000000000000..f5469ee8c69767 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-lto.py @@ -0,0 +1,66 @@ +#!/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]).decode('utf-8') + objtype = 'unknown' + if ': Mach-O ' in o: + objtype = 'mach-o' + elif ': LLVM bit' 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 --git a/tools/gyp/test/mac/gyptest-missing-cfbundlesignature.py b/tools/gyp/test/mac/gyptest-missing-cfbundlesignature.py new file mode 100644 index 00000000000000..be66492467c8d7 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-missing-cfbundlesignature.py @@ -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. + +""" +Verifies that an Info.plist with CFBundleSignature works. +""" + +from __future__ import print_function + +import TestGyp + +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') + test.build('test.gyp', test.ALL, chdir='missing-cfbundlesignature') + + test.built_file_must_match('mytarget.app/Contents/PkgInfo', 'APPL????', + chdir='missing-cfbundlesignature') + + test.built_file_must_match('myothertarget.app/Contents/PkgInfo', 'APPL????', + chdir='missing-cfbundlesignature') + + test.built_file_must_match('thirdtarget.app/Contents/PkgInfo', 'APPL????', + chdir='missing-cfbundlesignature') + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-non-strs-flattened-to-env.py b/tools/gyp/test/mac/gyptest-non-strs-flattened-to-env.py new file mode 100644 index 00000000000000..cb42a939d4ca4c --- /dev/null +++ b/tools/gyp/test/mac/gyptest-non-strs-flattened-to-env.py @@ -0,0 +1,38 @@ +#!/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 list xcode_settings are flattened before being exported to the +environment. +""" + +from __future__ import print_function + +import TestGyp + +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' + INFO_PLIST_PATH = 'Test.app/Contents/Info.plist' + + test.run_gyp('test.gyp', chdir=CHDIR) + test.build('test.gyp', test.ALL, chdir=CHDIR) + info_plist = test.built_file_path(INFO_PLIST_PATH, chdir=CHDIR) + test.must_exist(info_plist) + test.must_contain(info_plist, '''\ +\tMy Variable +\tsome expansion''') + test.must_contain(info_plist, '''\ +\tCFlags +\t-fstack-protector-all -fno-strict-aliasing -DS="A Space"''') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-objc-arc.py b/tools/gyp/test/mac/gyptest-objc-arc.py new file mode 100644 index 00000000000000..b3192a19dd37e2 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-objc-arc.py @@ -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. + +""" +Verifies that ARC objc settings are handled correctly. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + # set |match| to ignore build stderr output. + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], + match = lambda a, b: True) + + CHDIR = 'objc-arc' + test.run_gyp('test.gyp', chdir=CHDIR) + + test.build('test.gyp', 'arc_enabled', chdir=CHDIR) + test.build('test.gyp', 'arc_disabled', chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-objc-gc.py b/tools/gyp/test/mac/gyptest-objc-gc.py new file mode 100644 index 00000000000000..b6bcb6bc6730b0 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-objc-gc.py @@ -0,0 +1,48 @@ +#!/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 GC objc settings are handled correctly. +""" + +import TestGyp +from XCodeDetect import XCodeDetect + +# set |match| to ignore build stderr output. +test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], match=lambda a, b: True, platforms=['darwin']) + +# Xcode 5.1 removed support for garbage-collection: +# error: garbage collection is no longer supported +if XCodeDetect.Version() >= '0510': + test.skip_test('Test only on XCode < 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") + +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.pass_test() diff --git a/tools/gyp/test/mac/gyptest-postbuild-copy-bundle.py b/tools/gyp/test/mac/gyptest-postbuild-copy-bundle.py new file mode 100644 index 00000000000000..1f04d1cb36a073 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-postbuild-copy-bundle.py @@ -0,0 +1,75 @@ +#!/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 a postbuild copying a dependend framework into an app bundle is +rerun if the resources in the framework change. +""" + +import TestGyp + +import os.path +import sys + +if sys.platform == 'darwin': + # TODO(thakis): Make this pass with the make generator, http://crbug.com/95529 + test = TestGyp.TestGyp(formats=['ninja', 'xcode']) + + CHDIR = 'postbuild-copy-bundle' + test.run_gyp('test.gyp', 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') + final_resource_path = os.path.join(bundled_framework_dir, 'resource_file.sb') + final_copies_path = os.path.join( + app_bundle_dir, 'Contents', 'My Framework.framework', 'Versions', 'A', + 'Libraries', 'copied.txt') + + # Check that the dependency was built and copied into the app bundle: + test.build('test.gyp', 'test_app', chdir=CHDIR) + test.must_exist(final_resource_path) + test.must_match(final_resource_path, + 'This is included in the framework bundle.\n') + + test.must_exist(final_plist_path) + test.must_contain(final_plist_path, '''\ +\tRandomKey +\tRandomValue''') + + # Touch the dependency's bundle resource, and check that the modification + # makes it all the way into the app bundle: + test.sleep() + test.write('postbuild-copy-bundle/resource_file.sb', 'New text\n') + test.build('test.gyp', 'test_app', chdir=CHDIR) + + test.must_exist(final_resource_path) + test.must_match(final_resource_path, 'New text\n') + + # Check the same for the plist file. + test.sleep() + contents = test.read('postbuild-copy-bundle/Framework-Info.plist') + contents = contents.replace('RandomValue', 'NewRandomValue') + test.write('postbuild-copy-bundle/Framework-Info.plist', contents) + test.build('test.gyp', 'test_app', chdir=CHDIR) + + test.must_exist(final_plist_path) + test.must_contain(final_plist_path, '''\ +\tRandomKey +\tNewRandomValue''') + + # Check the same for the copies section, test for http://crbug.com/157077 + test.sleep() + contents = test.read('postbuild-copy-bundle/copied.txt') + contents = contents.replace('old', 'new') + test.write('postbuild-copy-bundle/copied.txt', contents) + test.build('test.gyp', 'test_app', chdir=CHDIR) + + test.must_exist(final_copies_path) + test.must_contain(final_copies_path, 'new copied file') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-postbuild-defaults.py b/tools/gyp/test/mac/gyptest-postbuild-defaults.py new file mode 100644 index 00000000000000..0f7d25bd89b747 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-postbuild-defaults.py @@ -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. + +""" +Verifies that a postbuild invoking |defaults| works. +""" + +from __future__ import print_function + +import TestGyp + +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' + test.run_gyp('test.gyp', chdir=CHDIR) + test.build('test.gyp', test.ALL, chdir=CHDIR) + + result_file = test.built_file_path('result', chdir=CHDIR) + test.must_exist(result_file) + test.must_contain(result_file, '''\ +Test +${PRODUCT_NAME} +''') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-postbuild-fail.py b/tools/gyp/test/mac/gyptest-postbuild-fail.py new file mode 100644 index 00000000000000..5d4485799abe47 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-postbuild-fail.py @@ -0,0 +1,53 @@ +#!/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 a failing postbuild step lets the build fail. +""" + +from __future__ import print_function + +import sys + +import TestGyp +from XCodeDetect import XCodeDetect + +# set |match| to ignore build stderr output. +test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], match=lambda a, b: True, platforms=['darwin']) + +if XCodeDetect.Version()[0] == '3': + print('Skip test on XCode 3') + sys.exit(2) + +test.run_gyp('test.gyp', chdir='postbuild-fail') + +build_error_code = { + 'xcode': [1, 65], # 1 for xcode 3, 65 for xcode 4 (see `man sysexits`) + 'make': 2, + 'ninja': 1, + 'xcode-ninja': [1, 65], +}[test.format] + +# If a postbuild fails, all postbuilds should be re-run on the next build. +# In Xcode 3, even if the first postbuild fails the other postbuilds were +# still executed. In Xcode 4, postbuilds are stopped after the first +# failing postbuild. This test checks for the Xcode 4 behavior. + +# Non-bundles +test.build('test.gyp', 'nonbundle', chdir='postbuild-fail', status=build_error_code) +test.built_file_must_not_exist('static_touch', chdir='postbuild-fail') +# Check for non-up-to-date-ness by checking if building again produces an +# error. +test.build('test.gyp', 'nonbundle', chdir='postbuild-fail', status=build_error_code) + +# Bundles +test.build('test.gyp', 'bundle', chdir='postbuild-fail', status=build_error_code) +test.built_file_must_not_exist('dynamic_touch', chdir='postbuild-fail') +# Check for non-up-to-date-ness by checking if building again produces an +# error. +test.build('test.gyp', 'bundle', chdir='postbuild-fail', status=build_error_code) + +test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-postbuild-multiple-configurations.py b/tools/gyp/test/mac/gyptest-postbuild-multiple-configurations.py new file mode 100644 index 00000000000000..84694f36ccadd3 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-postbuild-multiple-configurations.py @@ -0,0 +1,26 @@ +#!/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 a postbuild work in projects with multiple configurations. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + + CHDIR = 'postbuild-multiple-configurations' + test.run_gyp('test.gyp', chdir=CHDIR) + + for configuration in ['Debug', 'Release']: + test.set_configuration(configuration) + test.build('test.gyp', test.ALL, chdir=CHDIR) + test.built_file_must_exist('postbuild-file', chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-postbuild-static-library.py b/tools/gyp/test/mac/gyptest-postbuild-static-library.py new file mode 100644 index 00000000000000..8f9a6ebcb09de6 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-postbuild-static-library.py @@ -0,0 +1,28 @@ +#!/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 a postbuilds on static libraries work, and that sourceless +libraries don't cause failures at gyp time. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['make', 'xcode']) + + CHDIR = 'postbuild-static-library' + test.run_gyp('test.gyp', chdir=CHDIR) + test.build('test.gyp', 'my_lib', chdir=CHDIR) + # Building my_sourceless_lib doesn't work with make. gyp should probably + # forbid sourceless static libraries, since they're pretty pointless. + # But they shouldn't cause gyp time exceptions. + + test.built_file_must_exist('postbuild-file', chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-postbuild.py b/tools/gyp/test/mac/gyptest-postbuild.py new file mode 100644 index 00000000000000..684e7b8426d1de --- /dev/null +++ b/tools/gyp/test/mac/gyptest-postbuild.py @@ -0,0 +1,53 @@ +#!/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 postbuild steps work. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + + test.run_gyp('test.gyp', chdir='postbuilds') + + test.build('test.gyp', test.ALL, chdir='postbuilds') + + # See comment in test/subdirectory/gyptest-subdir-default.py + if test.format == 'xcode': + chdir = 'postbuilds/subdirectory' + else: + chdir = 'postbuilds' + + # Created by the postbuild scripts + test.built_file_must_exist('el.a_touch', + type=test.STATIC_LIB, + chdir='postbuilds') + test.built_file_must_exist('el.a_gyp_touch', + type=test.STATIC_LIB, + chdir='postbuilds') + test.built_file_must_exist('nest_el.a_touch', + type=test.STATIC_LIB, + chdir=chdir) + test.built_file_must_exist( + 'dyna.framework/Versions/A/dyna_touch', + chdir='postbuilds') + test.built_file_must_exist( + 'dyna.framework/Versions/A/dyna_gyp_touch', + chdir='postbuilds') + test.built_file_must_exist( + 'nest_dyna.framework/Versions/A/nest_dyna_touch', + chdir=chdir) + test.built_file_must_exist('dyna_standalone.dylib_gyp_touch', + type=test.SHARED_LIB, + chdir='postbuilds') + test.built_file_must_exist('copied_file.txt', chdir='postbuilds') + test.built_file_must_exist('copied_file_2.txt', chdir=chdir) + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-prefixheader.py b/tools/gyp/test/mac/gyptest-prefixheader.py new file mode 100644 index 00000000000000..0cf85f94225bf8 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-prefixheader.py @@ -0,0 +1,20 @@ +#!/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 GCC_PREFIX_HEADER works. +""" + +import TestGyp + +import sys + +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 --git a/tools/gyp/test/mac/gyptest-rebuild.py b/tools/gyp/test/mac/gyptest-rebuild.py new file mode 100644 index 00000000000000..c7d8cad02d5563 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-rebuild.py @@ -0,0 +1,46 @@ +#!/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 rebuilt correctly. +""" + +from __future__ import print_function + +import TestGyp + +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' + test.run_gyp('test.gyp', chdir=CHDIR) + + test.build('test.gyp', 'test_app', chdir=CHDIR) + + # Touch a source file, rebuild, and check that the app target is up-to-date. + test.touch('rebuild/main.c') + test.build('test.gyp', 'test_app', chdir=CHDIR) + + test.up_to_date('test.gyp', 'test_app', chdir=CHDIR) + + # Xcode runs postbuilds on every build, so targets with postbuilds are + # never marked as up_to_date. + if test.format != 'xcode': + # Same for a framework bundle. + test.build('test.gyp', 'test_framework_postbuilds', chdir=CHDIR) + test.up_to_date('test.gyp', 'test_framework_postbuilds', chdir=CHDIR) + + # Test that an app bundle with a postbuild that touches the app binary needs + # to be built only once. + test.build('test.gyp', 'test_app_postbuilds', chdir=CHDIR) + test.up_to_date('test.gyp', 'test_app_postbuilds', chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-rpath.py b/tools/gyp/test/mac/gyptest-rpath.py new file mode 100644 index 00000000000000..a82e2fd5620530 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-rpath.py @@ -0,0 +1,50 @@ +#!/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 LD_DYLIB_INSTALL_NAME and DYLIB_INSTALL_NAME_BASE are handled +correctly. +""" + +import TestGyp + +import re +import subprocess +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + + CHDIR = 'rpath' + test.run_gyp('test.gyp', chdir=CHDIR) + + test.build('test.gyp', test.ALL, chdir=CHDIR) + + def GetRpaths(p): + p = test.built_file_path(p, chdir=CHDIR) + r = re.compile(r'cmd LC_RPATH.*?path (.*?) \(offset \d+\)', re.DOTALL) + proc = subprocess.Popen(['otool', '-l', p], stdout=subprocess.PIPE) + o = proc.communicate()[0].decode('utf-8') + assert not proc.returncode + return r.findall(o) + + if GetRpaths('libdefault_rpath.dylib') != []: + test.fail_test() + + 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/.']: + test.fail_test() + + if GetRpaths('executable') != ['@executable_path/.']: + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-sdkroot.py b/tools/gyp/test/mac/gyptest-sdkroot.py new file mode 100644 index 00000000000000..f8edbaa583de1b --- /dev/null +++ b/tools/gyp/test/mac/gyptest-sdkroot.py @@ -0,0 +1,56 @@ +#!/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 setting SDKROOT works. +""" + +from __future__ import print_function + +import TestGyp + +import os +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 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) + + test.run_gyp('test.gyp', '-D', 'sdk_path=%s' % sdk_path, + chdir='sdkroot') + test.build('test.gyp', test.ALL, chdir='sdkroot') + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-sourceless-module.py b/tools/gyp/test/mac/gyptest-sourceless-module.py new file mode 100644 index 00000000000000..f2801c20aa2397 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-sourceless-module.py @@ -0,0 +1,77 @@ +#!/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 bundles that have no 'sources' (pure resource containers) work. +""" + +from __future__ import print_function + +import TestGyp + +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') + + # Just needs to build without errors. + test.build('test.gyp', 'empty_bundle', chdir='sourceless-module') + test.built_file_must_not_exist( + 'empty_bundle.bundle', chdir='sourceless-module') + + # Needs to build, and contain a resource. + test.build('test.gyp', 'resource_bundle', chdir='sourceless-module') + + test.built_file_must_exist( + 'resource_bundle.bundle/Contents/Resources/foo.manifest', + chdir='sourceless-module') + test.built_file_must_not_exist( + 'resource_bundle.bundle/Contents/MacOS/resource_bundle', + chdir='sourceless-module') + + # Build an app containing an actionless bundle. + test.build( + 'test.gyp', + 'bundle_dependent_on_resource_bundle_no_actions', + chdir='sourceless-module') + + test.built_file_must_exist( + 'bundle_dependent_on_resource_bundle_no_actions.app/Contents/Resources/' + 'mac_resource_bundle_no_actions.bundle/Contents/Resources/empty.txt', + chdir='sourceless-module') + + # Needs to build and cause the bundle to be built. + test.build( + 'test.gyp', 'dependent_on_resource_bundle', chdir='sourceless-module') + + test.built_file_must_exist( + 'resource_bundle.bundle/Contents/Resources/foo.manifest', + chdir='sourceless-module') + test.built_file_must_not_exist( + 'resource_bundle.bundle/Contents/MacOS/resource_bundle', + chdir='sourceless-module') + + # TODO(thakis): shared_libraries that have no sources but depend on static + # libraries currently only work with the ninja generator. This is used by + # chrome/mac's components build. + if test.format == 'ninja': + # Check that an executable depending on a resource framework links fine too. + test.build( + 'test.gyp', 'dependent_on_resource_framework', chdir='sourceless-module') + + test.built_file_must_exist( + 'resource_framework.framework/Resources/foo.manifest', + chdir='sourceless-module') + test.built_file_must_exist( + 'resource_framework.framework/resource_framework', + chdir='sourceless-module') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-strip-default.py b/tools/gyp/test/mac/gyptest-strip-default.py new file mode 100644 index 00000000000000..b851782fd52d69 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-strip-default.py @@ -0,0 +1,97 @@ +#!/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. +""" + +from __future__ import print_function + +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].decode('utf-8') + + # 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 --git a/tools/gyp/test/mac/gyptest-strip.py b/tools/gyp/test/mac/gyptest-strip.py new file mode 100644 index 00000000000000..96157e62cb24fb --- /dev/null +++ b/tools/gyp/test/mac/gyptest-strip.py @@ -0,0 +1,62 @@ +#!/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 stripping works. +""" + +from __future__ import print_function + +import re +import subprocess + +import TestGyp +from XCodeDetect import XCodeDetect + +test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], disable="This test is currently disabled: https://crbug.com/483696.", platforms=['darwin']) + +test.run_gyp('test.gyp', chdir='strip') + +test.build('test.gyp', test.ALL, chdir='strip') + + +# Lightweight check if stripping was done. +def OutPath(s): + return test.built_file_path(s, type=test.SHARED_LIB, chdir='strip') + + +def CheckNsyms(p, n_expected): + r = re.compile(r'nsyms\s+(\d+)') + 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 XCodeDetect.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'), 29 + expected_extra_symbol_count) +CheckNsyms(OutPath('no_strip'), 29 + expected_extra_symbol_count) +CheckNsyms(OutPath('strip_all'), 0) +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'), 7) + +test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-swift-library.py b/tools/gyp/test/mac/gyptest-swift-library.py new file mode 100644 index 00000000000000..08a6f456ca2158 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-swift-library.py @@ -0,0 +1,62 @@ +#!/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. +""" + +from __future__ import print_function + +import collections +import subprocess + +import TestGyp +from XCodeDetect import XCodeDetect + +test = TestGyp.TestGyp(formats=['xcode'], disable="This test is currently disabled: https://crbug.com/483696.", platforms=['darwin']) + +# 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 symbol: %s' % symbol) + test.fail_test() + +test_cases = [] + +# Run this for iOS on XCode 6.0 or greater +if XCodeDetect.Version() >= '0600': + test_cases.append(('Default', 'iphoneos')) + test_cases.append(('Default', 'iphonesimulator')) + +# Run it for Mac on XCode 6.1 or greater +if XCodeDetect.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 --git a/tools/gyp/test/mac/gyptest-type-envvars.py b/tools/gyp/test/mac/gyptest-type-envvars.py new file mode 100644 index 00000000000000..d7a583ef8b30f2 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-type-envvars.py @@ -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. + +""" +Test that MACH_O_TYPE etc are set correctly. +""" + +import os +import sys + +if sys.platform != 'darwin' or os.environ.get('TRAVIS') == 'true': + print('only for macOS') + sys.exit(2) + +import TestGyp + +test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + +test.run_gyp('test.gyp', '-G', 'xcode_ninja_target_pattern=^(?!nonbundle_none).*$', chdir='type_envvars') + +# The actual test is done by postbuild scripts during |test.build()|. +test.build('test.gyp', test.ALL, chdir='type_envvars') diff --git a/tools/gyp/test/mac/gyptest-unicode-settings.py b/tools/gyp/test/mac/gyptest-unicode-settings.py new file mode 100644 index 00000000000000..a71b3bd9a32eea --- /dev/null +++ b/tools/gyp/test/mac/gyptest-unicode-settings.py @@ -0,0 +1,20 @@ +#!/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. + +""" +Verifies that unicode strings in 'xcode_settings' work. +Also checks that ASCII control characters are escaped properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['xcode']) + test.run_gyp('test.gyp', chdir='unicode-settings') + test.build('test.gyp', test.ALL, chdir='unicode-settings') + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-xcode-env-order.py b/tools/gyp/test/mac/gyptest-xcode-env-order.py new file mode 100644 index 00000000000000..a2d0ea9b93b123 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-xcode-env-order.py @@ -0,0 +1,85 @@ +#!/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 dependent Xcode settings are processed correctly. +""" +import TestGyp +from XCodeDetect import XCodeDetect + +test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], disable="This test is currently disabled: https://crbug.com/483696.", platforms=['darwin']) + +CHDIR = 'xcode-env-order' +INFO_PLIST_PATH = 'Test.app/Contents/Info.plist' + +test.run_gyp('test.gyp', chdir=CHDIR) +test.build('test.gyp', test.ALL, chdir=CHDIR) + +# Env vars in 'copies' filenames. +test.built_file_must_exist('Test-copy-brace/main.c', chdir=CHDIR) +test.built_file_must_exist('Test-copy-paren/main.c', chdir=CHDIR) +test.built_file_must_exist('Test-copy-bare/main.c', chdir=CHDIR) + +# Env vars in 'actions' filenames and inline actions +test.built_file_must_exist('action-copy-brace.txt', chdir=CHDIR) +test.built_file_must_exist('action-copy-paren.txt', chdir=CHDIR) +test.built_file_must_exist('action-copy-bare.txt', chdir=CHDIR) + +# Env vars in 'rules' filenames and inline actions +test.built_file_must_exist('rule-copy-brace.txt', chdir=CHDIR) +test.built_file_must_exist('rule-copy-paren.txt', chdir=CHDIR) +# TODO: see comment in test.gyp for this file. +#test.built_file_must_exist('rule-copy-bare.txt', chdir=CHDIR) + +# Env vars in Info.plist. +info_plist = test.built_file_path(INFO_PLIST_PATH, chdir=CHDIR) +test.must_exist(info_plist) + +test.must_contain(info_plist, '''\ +\tBraceProcessedKey1 +\tD:/Source/Project/Test''') +test.must_contain(info_plist, '''\ +\tBraceProcessedKey2 +\t/Source/Project/Test''') +test.must_contain(info_plist, '''\ +\tBraceProcessedKey3 +\tcom.apple.product-type.application:D:/Source/Project/Test''') + +test.must_contain(info_plist, '''\ +\tParenProcessedKey1 +\tD:/Source/Project/Test''') +test.must_contain(info_plist, '''\ +\tParenProcessedKey2 +\t/Source/Project/Test''') +test.must_contain(info_plist, '''\ +\tParenProcessedKey3 +\tcom.apple.product-type.application:D:/Source/Project/Test''') + +test.must_contain(info_plist, '''\ +\tBareProcessedKey1 +\tD:/Source/Project/Test''') +test.must_contain(info_plist, '''\ +\tBareProcessedKey2 +\t/Source/Project/Test''') +# NOTE: For bare variables, $PRODUCT_TYPE is not replaced! It _is_ replaced +# 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' and XCodeDetect.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 +\t/Source/Project:Test:mh_execute''') + +test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-xcode-gcc-clang.py b/tools/gyp/test/mac/gyptest-xcode-gcc-clang.py new file mode 100644 index 00000000000000..d446b18108bafe --- /dev/null +++ b/tools/gyp/test/mac/gyptest-xcode-gcc-clang.py @@ -0,0 +1,39 @@ +#!/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 xcode-style GCC_... settings that require clang are handled +properly. +""" + +import TestGyp + +import os +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + + CHDIR = 'xcode-gcc' + test.run_gyp('test-clang.gyp', chdir=CHDIR) + + test.build('test-clang.gyp', 'aliasing_yes', chdir=CHDIR) + test.run_built_executable('aliasing_yes', chdir=CHDIR, stdout="1\n") + test.build('test-clang.gyp', 'aliasing_no', chdir=CHDIR) + test.run_built_executable('aliasing_no', chdir=CHDIR, stdout="0\n") + + # The default behavior changed: strict aliasing used to be off, now it's on + # by default. The important part is that this is identical for all generators + # (which it is). TODO(thakis): Enable this once the bots have a newer Xcode. + #test.build('test-clang.gyp', 'aliasing_default', chdir=CHDIR) + #test.run_built_executable('aliasing_default', chdir=CHDIR, stdout="1\n") + # For now, just check the generated ninja file: + if test.format == 'ninja': + contents = open(test.built_file_path('obj/aliasing_default.ninja', chdir=CHDIR)).read() + if 'strict-aliasing' in contents: + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-xcode-gcc.py b/tools/gyp/test/mac/gyptest-xcode-gcc.py new file mode 100644 index 00000000000000..26fe43d830f316 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-xcode-gcc.py @@ -0,0 +1,51 @@ +#!/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 xcode-style GCC_... settings are handled properly. +""" + +import TestGyp + +import subprocess +import sys + +def CompilerVersion(compiler): + stdout = subprocess.check_output([compiler, '-v'], stderr=subprocess.STDOUT) + stdout = stdout.decode('utf-8') + return stdout.rstrip('\n') + + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + + if test.format == 'xcode-ninja': + test.skip_test() + + CHDIR = 'xcode-gcc' + test.run_gyp('test.gyp', chdir=CHDIR) + + # List of targets that'll pass. It expects targets of the same name with + # '-fail' appended that'll fail to build. + targets = [ + 'warn_about_missing_newline', + ] + + # "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. + if 'clang' not in CompilerVersion('/usr/bin/cc'): + targets.append('warn_about_invalid_offsetof_macro') + + for target in targets: + test.build('test.gyp', target, chdir=CHDIR) + test.built_file_must_exist(target, chdir=CHDIR) + fail_target = target + '-fail' + test.build('test.gyp', fail_target, chdir=CHDIR, status=None, stderr=None, match=lambda *args: True) + test.built_file_must_not_exist(fail_target, chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-xcode-support-actions.py b/tools/gyp/test/mac/gyptest-xcode-support-actions.py new file mode 100644 index 00000000000000..ecc1402972cd80 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-xcode-support-actions.py @@ -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 --git a/tools/gyp/test/mac/gyptest-xctest.py b/tools/gyp/test/mac/gyptest-xctest.py new file mode 100644 index 00000000000000..fb478bb31c443d --- /dev/null +++ b/tools/gyp/test/mac/gyptest-xctest.py @@ -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 xctest targets are correctly configured. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['xcode']) + + # This test appears to be flaky. + test.skip_test() # bug=531 + + # 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 --git a/tools/gyp/test/mac/gyptest-xcuitest.py b/tools/gyp/test/mac/gyptest-xcuitest.py new file mode 100644 index 00000000000000..410de297d00f55 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-xcuitest.py @@ -0,0 +1,39 @@ +#!/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 xcuitest 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.decode('utf-8').splitlines() + # Convert the version string from 'Xcode 5.0' to ['5','0']. + xcode_version = xcode_version.split()[-1].split('.') + if xcode_version < ['7']: + test.pass_test() + + CHDIR = 'xcuitest' + test.run_gyp('test.gyp', chdir=CHDIR) + test.build('test.gyp', chdir=CHDIR, arguments=[ + '-target', 'tests', + '-sdk', 'iphonesimulator', + ]) + + test.pass_test() diff --git a/tools/gyp/test/mac/identical-name/proxy/proxy.cc b/tools/gyp/test/mac/identical-name/proxy/proxy.cc new file mode 100644 index 00000000000000..8e1782da63d596 --- /dev/null +++ b/tools/gyp/test/mac/identical-name/proxy/proxy.cc @@ -0,0 +1,2 @@ +// Empty file + diff --git a/tools/gyp/test/mac/identical-name/proxy/proxy.gyp b/tools/gyp/test/mac/identical-name/proxy/proxy.gyp new file mode 100644 index 00000000000000..38f44af1b57eec --- /dev/null +++ b/tools/gyp/test/mac/identical-name/proxy/proxy.gyp @@ -0,0 +1,9 @@ +{ + 'includes': ['../test.gypi'], + 'targets': [{ + 'target_name': 'testlib', + 'type': 'none', + 'dependencies': ['testlib/testlib.gyp:testlib'], + 'sources': ['proxy.cc'], + }], +} diff --git a/tools/gyp/test/mac/identical-name/proxy/testlib/testlib.cc b/tools/gyp/test/mac/identical-name/proxy/testlib/testlib.cc new file mode 100644 index 00000000000000..8e1782da63d596 --- /dev/null +++ b/tools/gyp/test/mac/identical-name/proxy/testlib/testlib.cc @@ -0,0 +1,2 @@ +// Empty file + diff --git a/tools/gyp/test/mac/identical-name/proxy/testlib/testlib.gyp b/tools/gyp/test/mac/identical-name/proxy/testlib/testlib.gyp new file mode 100644 index 00000000000000..ed1c62e982eaf0 --- /dev/null +++ b/tools/gyp/test/mac/identical-name/proxy/testlib/testlib.gyp @@ -0,0 +1,8 @@ +{ + 'includes': ['../../test.gypi'], + 'targets': [{ + 'target_name': 'testlib', + 'type': 'static_library', + 'sources': ['testlib.cc'], + }], +} diff --git a/tools/gyp/test/mac/identical-name/test-should-fail.gyp b/tools/gyp/test/mac/identical-name/test-should-fail.gyp new file mode 100644 index 00000000000000..72bfc7af0f8ef0 --- /dev/null +++ b/tools/gyp/test/mac/identical-name/test-should-fail.gyp @@ -0,0 +1,10 @@ +{ + 'targets': [{ + 'target_name': 'test', + 'type': 'executable', + 'dependencies': [ + 'testlib/testlib.gyp:proxy', + 'proxy/proxy.gyp:testlib', + ], + }], +} diff --git a/tools/gyp/test/mac/identical-name/test.gyp b/tools/gyp/test/mac/identical-name/test.gyp new file mode 100644 index 00000000000000..717220e8666ad9 --- /dev/null +++ b/tools/gyp/test/mac/identical-name/test.gyp @@ -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 --git a/tools/gyp/test/mac/identical-name/test.gypi b/tools/gyp/test/mac/identical-name/test.gypi new file mode 100644 index 00000000000000..61b7c2badf3d63 --- /dev/null +++ b/tools/gyp/test/mac/identical-name/test.gypi @@ -0,0 +1,7 @@ +{ + 'target_defaults': { + 'xcode_settings': { + 'SYMROOT': '<(DEPTH)/$SRCROOT/', + }, + }, +} diff --git a/tools/gyp/test/mac/identical-name/testlib/main.cc b/tools/gyp/test/mac/identical-name/testlib/main.cc new file mode 100644 index 00000000000000..5c2fa9bb6a78e2 --- /dev/null +++ b/tools/gyp/test/mac/identical-name/testlib/main.cc @@ -0,0 +1,3 @@ +int main(int argc, char **argv) { + return 0; +} diff --git a/tools/gyp/test/mac/identical-name/testlib/testlib.gyp b/tools/gyp/test/mac/identical-name/testlib/testlib.gyp new file mode 100644 index 00000000000000..aa8b851004dc17 --- /dev/null +++ b/tools/gyp/test/mac/identical-name/testlib/testlib.gyp @@ -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 --git a/tools/gyp/test/mac/identical-name/testlib/void.cc b/tools/gyp/test/mac/identical-name/testlib/void.cc new file mode 100644 index 00000000000000..8e1782da63d596 --- /dev/null +++ b/tools/gyp/test/mac/identical-name/testlib/void.cc @@ -0,0 +1,2 @@ +// Empty file + diff --git a/tools/gyp/test/mac/infoplist-process/Info.plist b/tools/gyp/test/mac/infoplist-process/Info.plist new file mode 100644 index 00000000000000..cb65721f43b59b --- /dev/null +++ b/tools/gyp/test/mac/infoplist-process/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.google.${PRODUCT_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + ProcessedKey1 + PROCESSED_KEY1 + ProcessedKey2 + PROCESSED_KEY2 + + diff --git a/tools/gyp/test/mac/infoplist-process/main.c b/tools/gyp/test/mac/infoplist-process/main.c new file mode 100644 index 00000000000000..1bf4b2a11abd99 --- /dev/null +++ b/tools/gyp/test/mac/infoplist-process/main.c @@ -0,0 +1,7 @@ +// 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. + +int main() { + return 0; +} diff --git a/tools/gyp/test/mac/infoplist-process/test1.gyp b/tools/gyp/test/mac/infoplist-process/test1.gyp new file mode 100644 index 00000000000000..bc625a968be756 --- /dev/null +++ b/tools/gyp/test/mac/infoplist-process/test1.gyp @@ -0,0 +1,25 @@ +# 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': 'test_app', + 'product_name': 'Test', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'main.c', + ], + 'configurations': { + 'One': { + }, + }, + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + 'INFOPLIST_PREPROCESS': 'YES', + 'INFOPLIST_PREPROCESSOR_DEFINITIONS': 'PROCESSED_KEY1=Foo PROCESSED_KEY2=Bar', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/infoplist-process/test2.gyp b/tools/gyp/test/mac/infoplist-process/test2.gyp new file mode 100644 index 00000000000000..ecfbc9f64c9cff --- /dev/null +++ b/tools/gyp/test/mac/infoplist-process/test2.gyp @@ -0,0 +1,25 @@ +# 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': 'test_app', + 'product_name': 'Test', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'main.c', + ], + 'configurations': { + 'Two': { + }, + }, + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + 'INFOPLIST_PREPROCESS': 'YES', + 'INFOPLIST_PREPROCESSOR_DEFINITIONS': 'PROCESSED_KEY1="Foo (Bar)"', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/infoplist-process/test3.gyp b/tools/gyp/test/mac/infoplist-process/test3.gyp new file mode 100644 index 00000000000000..be8fe75a53ec7b --- /dev/null +++ b/tools/gyp/test/mac/infoplist-process/test3.gyp @@ -0,0 +1,25 @@ +# 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': 'test_app', + 'product_name': 'Test App', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'main.c', + ], + 'configurations': { + 'Three': { + }, + }, + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + 'INFOPLIST_PREPROCESS': 'NO', + 'INFOPLIST_PREPROCESSOR_DEFINITIONS': 'PROCESSED_KEY1=Foo', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/installname/Info.plist b/tools/gyp/test/mac/installname/Info.plist new file mode 100644 index 00000000000000..5e05a5190c8931 --- /dev/null +++ b/tools/gyp/test/mac/installname/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.yourcompany.${PRODUCT_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSPrincipalClass + + + diff --git a/tools/gyp/test/mac/installname/file.c b/tools/gyp/test/mac/installname/file.c new file mode 100644 index 00000000000000..a39fce095f2f3a --- /dev/null +++ b/tools/gyp/test/mac/installname/file.c @@ -0,0 +1 @@ +int f() { return 0; } diff --git a/tools/gyp/test/mac/installname/main.c b/tools/gyp/test/mac/installname/main.c new file mode 100644 index 00000000000000..237c8ce181774d --- /dev/null +++ b/tools/gyp/test/mac/installname/main.c @@ -0,0 +1 @@ +int main() {} diff --git a/tools/gyp/test/mac/installname/test.gyp b/tools/gyp/test/mac/installname/test.gyp new file mode 100644 index 00000000000000..60c867ff122a1b --- /dev/null +++ b/tools/gyp/test/mac/installname/test.gyp @@ -0,0 +1,93 @@ +# 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': 'default_installname', + 'type': 'shared_library', + 'sources': [ 'file.c' ], + }, + { + 'target_name': 'default_bundle_installname', + 'product_name': 'My Framework', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.c' ], + }, + { + 'target_name': 'explicit_installname', + 'type': 'shared_library', + 'sources': [ 'file.c' ], + 'xcode_settings': { + 'LD_DYLIB_INSTALL_NAME': 'Trapped in a dynamiclib factory', + }, + }, + { + 'target_name': 'explicit_installname_base', + 'type': 'shared_library', + 'sources': [ 'file.c' ], + 'xcode_settings': { + 'DYLIB_INSTALL_NAME_BASE': '@executable_path/../../..', + + }, + }, + { + 'target_name': 'explicit_installname_base_bundle', + 'product_name': 'My Other Framework', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.c' ], + 'xcode_settings': { + 'DYLIB_INSTALL_NAME_BASE': '@executable_path/../../..', + + }, + }, + { + 'target_name': 'both_base_and_installname', + 'type': 'shared_library', + 'sources': [ 'file.c' ], + 'xcode_settings': { + # LD_DYLIB_INSTALL_NAME wins. + 'LD_DYLIB_INSTALL_NAME': 'Still trapped in a dynamiclib factory', + 'DYLIB_INSTALL_NAME_BASE': '@executable_path/../../..', + }, + }, + { + 'target_name': 'explicit_installname_with_base', + 'type': 'shared_library', + 'sources': [ 'file.c' ], + 'xcode_settings': { + 'LD_DYLIB_INSTALL_NAME': '$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)', + }, + }, + { + 'target_name': 'explicit_installname_with_explicit_base', + 'type': 'shared_library', + 'sources': [ 'file.c' ], + 'xcode_settings': { + 'DYLIB_INSTALL_NAME_BASE': '@executable_path/..', + 'LD_DYLIB_INSTALL_NAME': '$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)', + }, + }, + { + 'target_name': 'executable', + 'type': 'executable', + 'sources': [ 'main.c' ], + 'xcode_settings': { + 'LD_DYLIB_INSTALL_NAME': 'Should be ignored for not shared_lib', + }, + }, + # Regression test for http://crbug.com/113918 + { + 'target_name': 'install_name_with_info_plist', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.c' ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + 'LD_DYLIB_INSTALL_NAME': '$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/kext/GypKext/GypKext-Info.plist b/tools/gyp/test/mac/kext/GypKext/GypKext-Info.plist new file mode 100644 index 00000000000000..84226099c14c13 --- /dev/null +++ b/tools/gyp/test/mac/kext/GypKext/GypKext-Info.plist @@ -0,0 +1,35 @@ + + + + + BuildMachineOSBuild + Doesn't matter, will be overwritten + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.google.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + KEXT + CFBundleShortVersionString + 1.0 + CFBundleSignature + ause + CFBundleVersion + 1 + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + OSBundleLibraries + + com.apple.kpi.libkern + 10.0 + + + diff --git a/tools/gyp/test/mac/kext/GypKext/GypKext.c b/tools/gyp/test/mac/kext/GypKext/GypKext.c new file mode 100644 index 00000000000000..9b611b0dc51ca2 --- /dev/null +++ b/tools/gyp/test/mac/kext/GypKext/GypKext.c @@ -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. + +#include +#include + +kern_return_t GypKext_start(kmod_info_t* ki, void* d) { + printf("GypKext has started.\n"); + return KERN_SUCCESS; +} + +kern_return_t GypKext_stop(kmod_info_t* ki, void* d) { + printf("GypKext has stopped.\n"); + return KERN_SUCCESS; +} diff --git a/tools/gyp/test/mac/kext/kext.gyp b/tools/gyp/test/mac/kext/kext.gyp new file mode 100644 index 00000000000000..5b93087543a3af --- /dev/null +++ b/tools/gyp/test/mac/kext/kext.gyp @@ -0,0 +1,18 @@ +# 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': 'gypkext', + 'product_name': 'GypKext', + 'type': 'mac_kernel_extension', + 'sources': [ + 'GypKext/GypKext.c', + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'GypKext/GypKext-Info.plist', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/ldflags-libtool/file.c b/tools/gyp/test/mac/ldflags-libtool/file.c new file mode 100644 index 00000000000000..56757a701bf5cf --- /dev/null +++ b/tools/gyp/test/mac/ldflags-libtool/file.c @@ -0,0 +1 @@ +void f() {} diff --git a/tools/gyp/test/mac/ldflags-libtool/test.gyp b/tools/gyp/test/mac/ldflags-libtool/test.gyp new file mode 100644 index 00000000000000..4e7aa07106bb53 --- /dev/null +++ b/tools/gyp/test/mac/ldflags-libtool/test.gyp @@ -0,0 +1,17 @@ +# 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': 'ldflags_passed_to_libtool', + 'type': 'static_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'OTHER_LDFLAGS': [ + '-fblorfen-horf-does-not-exist', + ], + }, + }, + ], +} diff --git a/tools/gyp/test/mac/ldflags/subdirectory/Info.plist b/tools/gyp/test/mac/ldflags/subdirectory/Info.plist new file mode 100644 index 00000000000000..5f5e9abfbb5d52 --- /dev/null +++ b/tools/gyp/test/mac/ldflags/subdirectory/Info.plist @@ -0,0 +1,8 @@ + + + + + CFBundleSignature + ???? + + diff --git a/tools/gyp/test/mac/ldflags/subdirectory/file.c b/tools/gyp/test/mac/ldflags/subdirectory/file.c new file mode 100644 index 00000000000000..90c45543bf62c1 --- /dev/null +++ b/tools/gyp/test/mac/ldflags/subdirectory/file.c @@ -0,0 +1,2 @@ +void f() {} +void g() {} diff --git a/tools/gyp/test/mac/ldflags/subdirectory/symbol_list.def b/tools/gyp/test/mac/ldflags/subdirectory/symbol_list.def new file mode 100644 index 00000000000000..0ab7543b1fddc3 --- /dev/null +++ b/tools/gyp/test/mac/ldflags/subdirectory/symbol_list.def @@ -0,0 +1 @@ +_f diff --git a/tools/gyp/test/mac/ldflags/subdirectory/test.gyp b/tools/gyp/test/mac/ldflags/subdirectory/test.gyp new file mode 100644 index 00000000000000..db00c7465ca05d --- /dev/null +++ b/tools/gyp/test/mac/ldflags/subdirectory/test.gyp @@ -0,0 +1,66 @@ +# 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': 'raw', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'OTHER_LDFLAGS': [ + '-exported_symbols_list symbol_list.def', + '-sectcreate __TEXT __info_plist Info.plist', + ], + }, + }, + # TODO(thakis): This form should ideally be supported, too. (But + # -Wlfoo,bar,baz is cleaner so people should use that anyway.) + #{ + # 'target_name': 'raw_sep', + # 'type': 'shared_library', + # 'sources': [ 'file.c', ], + # 'xcode_settings': { + # 'OTHER_LDFLAGS': [ + # '-exported_symbols_list', 'symbol_list.def', + # '-sectcreate', '__TEXT', '__info_plist', 'Info.plist', + # ], + # }, + #}, + { + 'target_name': 'wl_space', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'OTHER_LDFLAGS': [ + # Works because clang passes unknown files on to the linker. + '-Wl,-exported_symbols_list symbol_list.def', + ], + }, + }, + # TODO(thakis): This form should ideally be supported, too. (But + # -Wlfoo,bar,baz is cleaner so people should use that anyway.) + #{ + # 'target_name': 'wl_space_sep', + # 'type': 'shared_library', + # 'sources': [ 'file.c', ], + # 'xcode_settings': { + # 'OTHER_LDFLAGS': [ + # # Works because clang passes unknown files on to the linker. + # '-Wl,-exported_symbols_list', 'symbol_list.def', + # ], + # }, + #}, + { + 'target_name': 'wl_comma', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'OTHER_LDFLAGS': [ + '-Wl,-exported_symbols_list,symbol_list.def', + '-Wl,-sectcreate,__TEXT,__info_plist,Info.plist', + ], + }, + }, + ], +} diff --git a/tools/gyp/test/mac/libraries/subdir/README.txt b/tools/gyp/test/mac/libraries/subdir/README.txt new file mode 100644 index 00000000000000..4031ded85f6301 --- /dev/null +++ b/tools/gyp/test/mac/libraries/subdir/README.txt @@ -0,0 +1 @@ +Make things live in a subdirectory, to make sure that DEPTH works correctly. diff --git a/tools/gyp/test/mac/libraries/subdir/hello.cc b/tools/gyp/test/mac/libraries/subdir/hello.cc new file mode 100644 index 00000000000000..a43554c8caf8f0 --- /dev/null +++ b/tools/gyp/test/mac/libraries/subdir/hello.cc @@ -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::cout << "Hello, world!" << std::endl; + return 0; +} diff --git a/tools/gyp/test/mac/libraries/subdir/mylib.c b/tools/gyp/test/mac/libraries/subdir/mylib.c new file mode 100644 index 00000000000000..e771991e836a67 --- /dev/null +++ b/tools/gyp/test/mac/libraries/subdir/mylib.c @@ -0,0 +1,7 @@ +// 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. + +int my_foo(int x) { + return x + 1; +} diff --git a/tools/gyp/test/mac/libraries/subdir/test.gyp b/tools/gyp/test/mac/libraries/subdir/test.gyp new file mode 100644 index 00000000000000..59fef51017b5bc --- /dev/null +++ b/tools/gyp/test/mac/libraries/subdir/test.gyp @@ -0,0 +1,65 @@ +# 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': 'libraries-test', + 'type': 'executable', + 'sources': [ + 'hello.cc', + ], + 'link_settings': { + 'libraries': [ + 'libcrypto.dylib', + ], + }, + }, + { + # This creates a static library and puts it in a nonstandard location for + # libraries-search-path-test. + 'target_name': 'mylib', + 'type': 'static_library', + 'sources': [ + 'mylib.c', + ], + 'postbuilds': [ + { + 'postbuild_name': 'Make a secret location', + 'action': [ + 'mkdir', + '-p', + '${SRCROOT}/../secret_location', + ], + }, + { + 'postbuild_name': 'Copy to secret location, with secret name', + 'action': [ + 'cp', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}', + '${SRCROOT}/../secret_location/libmysecretlib.a', + ], + }, + ], + }, + { + 'target_name': 'libraries-search-path-test', + 'type': 'executable', + 'dependencies': [ 'mylib' ], + 'sources': [ + 'hello.cc', + ], + 'xcode_settings': { + 'LIBRARY_SEARCH_PATHS': [ + '<(DEPTH)/secret_location', + ], + }, + 'link_settings': { + 'libraries': [ + 'libmysecretlib.a', + ], + }, + }, + ], +} diff --git a/tools/gyp/test/mac/libtool-zero/mylib.c b/tools/gyp/test/mac/libtool-zero/mylib.c new file mode 100644 index 00000000000000..b26d61bd6ba917 --- /dev/null +++ b/tools/gyp/test/mac/libtool-zero/mylib.c @@ -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 --git a/tools/gyp/test/mac/libtool-zero/test.gyp b/tools/gyp/test/mac/libtool-zero/test.gyp new file mode 100644 index 00000000000000..0d6ee5535eede1 --- /dev/null +++ b/tools/gyp/test/mac/libtool-zero/test.gyp @@ -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 --git a/tools/gyp/test/mac/loadable-module-bundle-product-extension/src.cc b/tools/gyp/test/mac/loadable-module-bundle-product-extension/src.cc new file mode 100644 index 00000000000000..3d878e9697d61b --- /dev/null +++ b/tools/gyp/test/mac/loadable-module-bundle-product-extension/src.cc @@ -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 --git a/tools/gyp/test/mac/loadable-module-bundle-product-extension/test.gyp b/tools/gyp/test/mac/loadable-module-bundle-product-extension/test.gyp new file mode 100644 index 00000000000000..684a2c02aa33c4 --- /dev/null +++ b/tools/gyp/test/mac/loadable-module-bundle-product-extension/test.gyp @@ -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 --git a/tools/gyp/test/mac/loadable-module/Info.plist b/tools/gyp/test/mac/loadable-module/Info.plist new file mode 100644 index 00000000000000..f6607aebd91cae --- /dev/null +++ b/tools/gyp/test/mac/loadable-module/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.google.test_loadable_module + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BRPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + CFPlugInDynamicRegisterFunction + + CFPlugInDynamicRegistration + NO + + diff --git a/tools/gyp/test/mac/loadable-module/module.c b/tools/gyp/test/mac/loadable-module/module.c new file mode 100644 index 00000000000000..958453834744cb --- /dev/null +++ b/tools/gyp/test/mac/loadable-module/module.c @@ -0,0 +1,11 @@ +// 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. + +int SuperFly() { + return 42; +} + +const char* SuperFoo() { + return "Hello World"; +} diff --git a/tools/gyp/test/mac/loadable-module/test.gyp b/tools/gyp/test/mac/loadable-module/test.gyp new file mode 100644 index 00000000000000..3c8a5309d25879 --- /dev/null +++ b/tools/gyp/test/mac/loadable-module/test.gyp @@ -0,0 +1,18 @@ +# 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': 'test_loadable_module', + 'type': 'loadable_module', + 'mac_bundle': 1, + 'sources': [ 'module.c' ], + 'product_extension': 'plugin', + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/lto/asmfile.S b/tools/gyp/test/mac/lto/asmfile.S new file mode 100644 index 00000000000000..ea23759a39b9ce --- /dev/null +++ b/tools/gyp/test/mac/lto/asmfile.S @@ -0,0 +1,2 @@ +.globl _asfun +ret diff --git a/tools/gyp/test/mac/lto/ccfile.cc b/tools/gyp/test/mac/lto/ccfile.cc new file mode 100644 index 00000000000000..2503afd7b1670f --- /dev/null +++ b/tools/gyp/test/mac/lto/ccfile.cc @@ -0,0 +1 @@ +void ccfun() {} diff --git a/tools/gyp/test/mac/lto/cfile.c b/tools/gyp/test/mac/lto/cfile.c new file mode 100644 index 00000000000000..d02ef4b8d6848d --- /dev/null +++ b/tools/gyp/test/mac/lto/cfile.c @@ -0,0 +1 @@ +void cfun() {} diff --git a/tools/gyp/test/mac/lto/mfile.m b/tools/gyp/test/mac/lto/mfile.m new file mode 100644 index 00000000000000..85b7d93afef0d8 --- /dev/null +++ b/tools/gyp/test/mac/lto/mfile.m @@ -0,0 +1 @@ +void mfun() {} diff --git a/tools/gyp/test/mac/lto/mmfile.mm b/tools/gyp/test/mac/lto/mmfile.mm new file mode 100644 index 00000000000000..beaa3595f8039d --- /dev/null +++ b/tools/gyp/test/mac/lto/mmfile.mm @@ -0,0 +1 @@ +void mmfun() {} diff --git a/tools/gyp/test/mac/lto/test.gyp b/tools/gyp/test/mac/lto/test.gyp new file mode 100644 index 00000000000000..0a8e85183d7810 --- /dev/null +++ b/tools/gyp/test/mac/lto/test.gyp @@ -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 --git a/tools/gyp/test/mac/missing-cfbundlesignature/Info.plist b/tools/gyp/test/mac/missing-cfbundlesignature/Info.plist new file mode 100644 index 00000000000000..0c3167488440d6 --- /dev/null +++ b/tools/gyp/test/mac/missing-cfbundlesignature/Info.plist @@ -0,0 +1,10 @@ + + + + + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundlePackageType + APPL + + diff --git a/tools/gyp/test/mac/missing-cfbundlesignature/Other-Info.plist b/tools/gyp/test/mac/missing-cfbundlesignature/Other-Info.plist new file mode 100644 index 00000000000000..47095281c8a0c8 --- /dev/null +++ b/tools/gyp/test/mac/missing-cfbundlesignature/Other-Info.plist @@ -0,0 +1,12 @@ + + + + + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundlePackageType + APPL + CFBundleSignature + F + + diff --git a/tools/gyp/test/mac/missing-cfbundlesignature/Third-Info.plist b/tools/gyp/test/mac/missing-cfbundlesignature/Third-Info.plist new file mode 100644 index 00000000000000..5b61fe2664ec35 --- /dev/null +++ b/tools/gyp/test/mac/missing-cfbundlesignature/Third-Info.plist @@ -0,0 +1,12 @@ + + + + + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundlePackageType + APPL + CFBundleSignature + some really long string + + diff --git a/tools/gyp/test/mac/missing-cfbundlesignature/file.c b/tools/gyp/test/mac/missing-cfbundlesignature/file.c new file mode 100644 index 00000000000000..237c8ce181774d --- /dev/null +++ b/tools/gyp/test/mac/missing-cfbundlesignature/file.c @@ -0,0 +1 @@ +int main() {} diff --git a/tools/gyp/test/mac/missing-cfbundlesignature/test.gyp b/tools/gyp/test/mac/missing-cfbundlesignature/test.gyp new file mode 100644 index 00000000000000..b50cc2791a031d --- /dev/null +++ b/tools/gyp/test/mac/missing-cfbundlesignature/test.gyp @@ -0,0 +1,34 @@ +# 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': 'mytarget', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + }, + }, + { + 'target_name': 'myothertarget', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'Other-Info.plist', + }, + }, + { + 'target_name': 'thirdtarget', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'Third-Info.plist', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/non-strs-flattened-to-env/Info.plist b/tools/gyp/test/mac/non-strs-flattened-to-env/Info.plist new file mode 100644 index 00000000000000..11fc4b660d77cd --- /dev/null +++ b/tools/gyp/test/mac/non-strs-flattened-to-env/Info.plist @@ -0,0 +1,15 @@ + + + + + + CFBundlePackageType + APPL + CFBundleSignature + ???? + My Variable + ${MY_VAR} + CFlags + ${OTHER_CFLAGS} + + diff --git a/tools/gyp/test/mac/non-strs-flattened-to-env/main.c b/tools/gyp/test/mac/non-strs-flattened-to-env/main.c new file mode 100644 index 00000000000000..1711567ef56670 --- /dev/null +++ b/tools/gyp/test/mac/non-strs-flattened-to-env/main.c @@ -0,0 +1,7 @@ +// 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. + +int main() { + return 0; +} diff --git a/tools/gyp/test/mac/non-strs-flattened-to-env/test.gyp b/tools/gyp/test/mac/non-strs-flattened-to-env/test.gyp new file mode 100644 index 00000000000000..aaf821c9257010 --- /dev/null +++ b/tools/gyp/test/mac/non-strs-flattened-to-env/test.gyp @@ -0,0 +1,27 @@ +# 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_app', + 'product_name': 'Test', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ 'main.c', ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + 'MY_VAR': 'some expansion', + 'OTHER_CFLAGS': [ + # Just some (more than one) random flags. + '-fstack-protector-all', + '-fno-strict-aliasing', + '-DS="A Space"', # Would normally be in 'defines' + ], + }, + 'include_dirs': [ + '$(SDKROOT)/usr/include/libxml2', + ], + }, + ], +} diff --git a/tools/gyp/test/mac/objc-arc/c-file.c b/tools/gyp/test/mac/objc-arc/c-file.c new file mode 100644 index 00000000000000..653613206e5711 --- /dev/null +++ b/tools/gyp/test/mac/objc-arc/c-file.c @@ -0,0 +1,6 @@ +#if __has_feature(objc_arc) +#error "C files shouldn't be ARC'd!" +#endif + +void c_fun() {} + diff --git a/tools/gyp/test/mac/objc-arc/cc-file.cc b/tools/gyp/test/mac/objc-arc/cc-file.cc new file mode 100644 index 00000000000000..95e14ea3e053f1 --- /dev/null +++ b/tools/gyp/test/mac/objc-arc/cc-file.cc @@ -0,0 +1,5 @@ +#if __has_feature(objc_arc) +#error "C++ files shouldn't be ARC'd!" +#endif + +void cc_fun() {} diff --git a/tools/gyp/test/mac/objc-arc/m-file-no-arc.m b/tools/gyp/test/mac/objc-arc/m-file-no-arc.m new file mode 100644 index 00000000000000..8ffaabfaae5130 --- /dev/null +++ b/tools/gyp/test/mac/objc-arc/m-file-no-arc.m @@ -0,0 +1,5 @@ +#if __has_feature(objc_arc) +#error "ObjC files without CLANG_ENABLE_OBJC_ARC should not be ARC'd!" +#endif + +void m_fun() {} diff --git a/tools/gyp/test/mac/objc-arc/m-file.m b/tools/gyp/test/mac/objc-arc/m-file.m new file mode 100644 index 00000000000000..9689b1f8e5da5e --- /dev/null +++ b/tools/gyp/test/mac/objc-arc/m-file.m @@ -0,0 +1,5 @@ +#if !__has_feature(objc_arc) +#error "ObjC files with CLANG_ENABLE_OBJC_ARC should be ARC'd!" +#endif + +void m_fun() {} diff --git a/tools/gyp/test/mac/objc-arc/mm-file-no-arc.mm b/tools/gyp/test/mac/objc-arc/mm-file-no-arc.mm new file mode 100644 index 00000000000000..0dac5394948138 --- /dev/null +++ b/tools/gyp/test/mac/objc-arc/mm-file-no-arc.mm @@ -0,0 +1,5 @@ +#if __has_feature(objc_arc) +#error "ObjC++ files without CLANG_ENABLE_OBJC_ARC should not be ARC'd!" +#endif + +void mm_fun() {} diff --git a/tools/gyp/test/mac/objc-arc/mm-file.mm b/tools/gyp/test/mac/objc-arc/mm-file.mm new file mode 100644 index 00000000000000..9467e965633650 --- /dev/null +++ b/tools/gyp/test/mac/objc-arc/mm-file.mm @@ -0,0 +1,5 @@ +#if !__has_feature(objc_arc) +#error "ObjC++ files with CLANG_ENABLE_OBJC_ARC should be ARC'd!" +#endif + +void mm_fun() {} diff --git a/tools/gyp/test/mac/objc-arc/test.gyp b/tools/gyp/test/mac/objc-arc/test.gyp new file mode 100644 index 00000000000000..59cf0e29ceeb83 --- /dev/null +++ b/tools/gyp/test/mac/objc-arc/test.gyp @@ -0,0 +1,45 @@ +# 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'], + ['CXX', '/usr/bin/clang++'], + ], + + 'targets': [ + { + 'target_name': 'arc_enabled', + 'type': 'static_library', + 'sources': [ + 'c-file.c', + 'cc-file.cc', + 'm-file.m', + 'mm-file.mm', + ], + 'xcode_settings': { + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + 'MACOSX_DEPLOYMENT_TARGET': '10.6', + 'ARCHS': [ 'x86_64' ], # For the non-fragile objc ABI. + 'CLANG_ENABLE_OBJC_ARC': 'YES', + }, + }, + + { + 'target_name': 'arc_disabled', + 'type': 'static_library', + 'sources': [ + 'c-file.c', + 'cc-file.cc', + 'm-file-no-arc.m', + 'mm-file-no-arc.mm', + ], + 'xcode_settings': { + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + 'MACOSX_DEPLOYMENT_TARGET': '10.6', + 'ARCHS': [ 'x86_64' ], # For the non-fragile objc ABI. + }, + }, + ], +} + diff --git a/tools/gyp/test/mac/objc-gc/c-file.c b/tools/gyp/test/mac/objc-gc/c-file.c new file mode 100644 index 00000000000000..2855a00eaaa693 --- /dev/null +++ b/tools/gyp/test/mac/objc-gc/c-file.c @@ -0,0 +1 @@ +void c_fun() {} diff --git a/tools/gyp/test/mac/objc-gc/cc-file.cc b/tools/gyp/test/mac/objc-gc/cc-file.cc new file mode 100644 index 00000000000000..71e47a0126fea6 --- /dev/null +++ b/tools/gyp/test/mac/objc-gc/cc-file.cc @@ -0,0 +1 @@ +void cc_fun() {} diff --git a/tools/gyp/test/mac/objc-gc/main.m b/tools/gyp/test/mac/objc-gc/main.m new file mode 100644 index 00000000000000..1a87f8e70fe29c --- /dev/null +++ b/tools/gyp/test/mac/objc-gc/main.m @@ -0,0 +1,6 @@ +#import + +int main() { + printf("gc on: %d\n", [NSGarbageCollector defaultCollector] != NULL); + return 0; +} diff --git a/tools/gyp/test/mac/objc-gc/needs-gc-mm.mm b/tools/gyp/test/mac/objc-gc/needs-gc-mm.mm new file mode 100644 index 00000000000000..fc3fee9f34ab7b --- /dev/null +++ b/tools/gyp/test/mac/objc-gc/needs-gc-mm.mm @@ -0,0 +1 @@ +void objcpp_fun() { } diff --git a/tools/gyp/test/mac/objc-gc/needs-gc.m b/tools/gyp/test/mac/objc-gc/needs-gc.m new file mode 100644 index 00000000000000..ca77976b1da1b6 --- /dev/null +++ b/tools/gyp/test/mac/objc-gc/needs-gc.m @@ -0,0 +1 @@ +void objc_fun() { } diff --git a/tools/gyp/test/mac/objc-gc/test.gyp b/tools/gyp/test/mac/objc-gc/test.gyp new file mode 100644 index 00000000000000..4d827c1b39c543 --- /dev/null +++ b/tools/gyp/test/mac/objc-gc/test.gyp @@ -0,0 +1,102 @@ +# 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': [ + # For some reason, static_library targets that are built with gc=required + # and then linked to executables that don't use gc, the linker doesn't + # complain. For shared_libraries it does, so use that. + { + 'target_name': 'no_gc_lib', + 'type': 'shared_library', + 'sources': [ + 'c-file.c', + 'cc-file.cc', + 'needs-gc-mm.mm', + 'needs-gc.m', + ], + }, + { + 'target_name': 'gc_lib', + 'type': 'shared_library', + 'sources': [ + 'c-file.c', + 'cc-file.cc', + 'needs-gc-mm.mm', + 'needs-gc.m', + ], + 'xcode_settings': { + 'GCC_ENABLE_OBJC_GC': 'supported', + }, + }, + { + 'target_name': 'gc_req_lib', + 'type': 'shared_library', + 'sources': [ + 'c-file.c', + 'cc-file.cc', + 'needs-gc-mm.mm', + 'needs-gc.m', + ], + 'xcode_settings': { + 'GCC_ENABLE_OBJC_GC': 'required', + }, + }, + + { + 'target_name': 'gc_exe_fails', + 'type': 'executable', + 'sources': [ 'main.m' ], + 'dependencies': [ 'no_gc_lib' ], + 'xcode_settings': { + 'GCC_ENABLE_OBJC_GC': 'required', + }, + 'libraries': [ 'Foundation.framework' ], + }, + { + 'target_name': 'gc_req_exe', + 'type': 'executable', + 'sources': [ 'main.m' ], + 'dependencies': [ 'gc_lib' ], + 'xcode_settings': { + 'GCC_ENABLE_OBJC_GC': 'required', + }, + 'libraries': [ 'Foundation.framework' ], + }, + { + 'target_name': 'gc_exe_req_lib', + 'type': 'executable', + 'sources': [ 'main.m' ], + 'dependencies': [ 'gc_req_lib' ], + 'xcode_settings': { + 'GCC_ENABLE_OBJC_GC': 'supported', + }, + 'libraries': [ 'Foundation.framework' ], + }, + { + 'target_name': 'gc_exe', + 'type': 'executable', + 'sources': [ 'main.m' ], + 'dependencies': [ 'gc_lib' ], + 'xcode_settings': { + 'GCC_ENABLE_OBJC_GC': 'supported', + }, + 'libraries': [ 'Foundation.framework' ], + }, + { + 'target_name': 'gc_off_exe_req_lib', + 'type': 'executable', + 'sources': [ 'main.m' ], + 'dependencies': [ 'gc_req_lib' ], + 'libraries': [ 'Foundation.framework' ], + }, + { + 'target_name': 'gc_off_exe', + 'type': 'executable', + 'sources': [ 'main.m' ], + 'dependencies': [ 'gc_lib' ], + 'libraries': [ 'Foundation.framework' ], + }, + ], +} + diff --git a/tools/gyp/test/mac/postbuild-copy-bundle/Framework-Info.plist b/tools/gyp/test/mac/postbuild-copy-bundle/Framework-Info.plist new file mode 100644 index 00000000000000..ec36829c080546 --- /dev/null +++ b/tools/gyp/test/mac/postbuild-copy-bundle/Framework-Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.yourcompany.${PRODUCT_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSPrincipalClass + + RandomKey + RandomValue + + diff --git a/tools/gyp/test/mac/postbuild-copy-bundle/TestApp-Info.plist b/tools/gyp/test/mac/postbuild-copy-bundle/TestApp-Info.plist new file mode 100644 index 00000000000000..98fd5152000f7b --- /dev/null +++ b/tools/gyp/test/mac/postbuild-copy-bundle/TestApp-Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.google.${PRODUCT_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tools/gyp/test/mac/postbuild-copy-bundle/copied.txt b/tools/gyp/test/mac/postbuild-copy-bundle/copied.txt new file mode 100644 index 00000000000000..178413886a8f4e --- /dev/null +++ b/tools/gyp/test/mac/postbuild-copy-bundle/copied.txt @@ -0,0 +1 @@ +old copied file diff --git a/tools/gyp/test/mac/postbuild-copy-bundle/empty.c b/tools/gyp/test/mac/postbuild-copy-bundle/empty.c new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/mac/postbuild-copy-bundle/main.c b/tools/gyp/test/mac/postbuild-copy-bundle/main.c new file mode 100644 index 00000000000000..21c19635262233 --- /dev/null +++ b/tools/gyp/test/mac/postbuild-copy-bundle/main.c @@ -0,0 +1,4 @@ +// 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. +int main() {} diff --git a/tools/gyp/test/mac/postbuild-copy-bundle/postbuild-copy-framework.sh b/tools/gyp/test/mac/postbuild-copy-bundle/postbuild-copy-framework.sh new file mode 100644 index 00000000000000..930fec66126d07 --- /dev/null +++ b/tools/gyp/test/mac/postbuild-copy-bundle/postbuild-copy-framework.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# 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. + +set -e + +rsync -acC --delete "$1" "$2" diff --git a/tools/gyp/test/mac/postbuild-copy-bundle/resource_file.sb b/tools/gyp/test/mac/postbuild-copy-bundle/resource_file.sb new file mode 100644 index 00000000000000..42057fa2357faf --- /dev/null +++ b/tools/gyp/test/mac/postbuild-copy-bundle/resource_file.sb @@ -0,0 +1 @@ +This is included in the framework bundle. diff --git a/tools/gyp/test/mac/postbuild-copy-bundle/test.gyp b/tools/gyp/test/mac/postbuild-copy-bundle/test.gyp new file mode 100644 index 00000000000000..a03e6432f2a469 --- /dev/null +++ b/tools/gyp/test/mac/postbuild-copy-bundle/test.gyp @@ -0,0 +1,49 @@ +# 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_bundle', + 'product_name': 'My Framework', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'empty.c', ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'Framework-Info.plist', + }, + 'mac_bundle_resources': [ + 'resource_file.sb', + ], + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/$(CONTENTS_FOLDER_PATH)/Libraries', + 'files': [ 'copied.txt' ], + }, + ], + }, + { + 'target_name': 'test_app', + 'product_name': 'Test App', + 'type': 'executable', + 'mac_bundle': 1, + 'dependencies': [ + 'test_bundle', + ], + 'sources': [ 'main.c', ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'TestApp-Info.plist', + }, + 'postbuilds': [ + { + 'postbuild_name': 'Copy dependent framework into app', + 'action': [ + './postbuild-copy-framework.sh', + '${BUILT_PRODUCTS_DIR}/My Framework.framework', + '${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/', + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/mac/postbuild-defaults/Info.plist b/tools/gyp/test/mac/postbuild-defaults/Info.plist new file mode 100644 index 00000000000000..d3f54d76cdc235 --- /dev/null +++ b/tools/gyp/test/mac/postbuild-defaults/Info.plist @@ -0,0 +1,13 @@ + + + + + + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleName + ${PRODUCT_NAME} + + diff --git a/tools/gyp/test/mac/postbuild-defaults/main.c b/tools/gyp/test/mac/postbuild-defaults/main.c new file mode 100644 index 00000000000000..1711567ef56670 --- /dev/null +++ b/tools/gyp/test/mac/postbuild-defaults/main.c @@ -0,0 +1,7 @@ +// 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. + +int main() { + return 0; +} diff --git a/tools/gyp/test/mac/postbuild-defaults/postbuild-defaults.sh b/tools/gyp/test/mac/postbuild-defaults/postbuild-defaults.sh new file mode 100644 index 00000000000000..56af2a8329bd67 --- /dev/null +++ b/tools/gyp/test/mac/postbuild-defaults/postbuild-defaults.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# 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. + +set -e + +# This is the built Info.plist in the output directory. +PLIST="${BUILT_PRODUCTS_DIR}"/Test.app/Contents/Info # No trailing .plist +echo $(defaults read "${PLIST}" "CFBundleName") > "${BUILT_PRODUCTS_DIR}/result" + +# This is the source Info.plist next to this script file. +PLIST="${SRCROOT}"/Info # No trailing .plist +echo $(defaults read "${PLIST}" "CFBundleName") \ + >> "${BUILT_PRODUCTS_DIR}/result" diff --git a/tools/gyp/test/mac/postbuild-defaults/test.gyp b/tools/gyp/test/mac/postbuild-defaults/test.gyp new file mode 100644 index 00000000000000..be0a075efc6f0c --- /dev/null +++ b/tools/gyp/test/mac/postbuild-defaults/test.gyp @@ -0,0 +1,26 @@ +# 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_app', + 'product_name': 'Test', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ 'main.c', ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + }, + 'postbuilds': [ + { + 'postbuild_name': 'Postbuild that calls defaults', + 'action': [ + './postbuild-defaults.sh', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}', + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/mac/postbuild-fail/file.c b/tools/gyp/test/mac/postbuild-fail/file.c new file mode 100644 index 00000000000000..91695b10c6f183 --- /dev/null +++ b/tools/gyp/test/mac/postbuild-fail/file.c @@ -0,0 +1,6 @@ +// 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. + +// That's right, this is copyrighted. +void f() {} diff --git a/tools/gyp/test/mac/postbuild-fail/postbuild-fail.sh b/tools/gyp/test/mac/postbuild-fail/postbuild-fail.sh new file mode 100644 index 00000000000000..dc1a60d987e288 --- /dev/null +++ b/tools/gyp/test/mac/postbuild-fail/postbuild-fail.sh @@ -0,0 +1,6 @@ +#!/usr/bin/bash +# 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. + +exit 1 diff --git a/tools/gyp/test/mac/postbuild-fail/test.gyp b/tools/gyp/test/mac/postbuild-fail/test.gyp new file mode 100644 index 00000000000000..e63283db036bdd --- /dev/null +++ b/tools/gyp/test/mac/postbuild-fail/test.gyp @@ -0,0 +1,38 @@ +# 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': 'nonbundle', + 'type': 'static_library', + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'Postbuild Fail', + 'action': [ './postbuild-fail.sh', ], + }, + { + 'postbuild_name': 'Runs after failing postbuild', + 'action': [ './touch-static.sh', ], + }, + ], + }, + { + 'target_name': 'bundle', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'Postbuild Fail', + 'action': [ './postbuild-fail.sh', ], + }, + { + 'postbuild_name': 'Runs after failing postbuild', + 'action': [ './touch-dynamic.sh', ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/mac/postbuild-fail/touch-dynamic.sh b/tools/gyp/test/mac/postbuild-fail/touch-dynamic.sh new file mode 100644 index 00000000000000..a388a64102bf6b --- /dev/null +++ b/tools/gyp/test/mac/postbuild-fail/touch-dynamic.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# 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. + +set -e +touch "${BUILT_PRODUCTS_DIR}/dynamic_touch" diff --git a/tools/gyp/test/mac/postbuild-fail/touch-static.sh b/tools/gyp/test/mac/postbuild-fail/touch-static.sh new file mode 100644 index 00000000000000..97ecaa68682f51 --- /dev/null +++ b/tools/gyp/test/mac/postbuild-fail/touch-static.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# 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. + +set -e +touch "${BUILT_PRODUCTS_DIR}/static_touch" diff --git a/tools/gyp/test/mac/postbuild-multiple-configurations/main.c b/tools/gyp/test/mac/postbuild-multiple-configurations/main.c new file mode 100644 index 00000000000000..21c19635262233 --- /dev/null +++ b/tools/gyp/test/mac/postbuild-multiple-configurations/main.c @@ -0,0 +1,4 @@ +// 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. +int main() {} diff --git a/tools/gyp/test/mac/postbuild-multiple-configurations/postbuild-touch-file.sh b/tools/gyp/test/mac/postbuild-multiple-configurations/postbuild-touch-file.sh new file mode 100644 index 00000000000000..b6170cf7a7f863 --- /dev/null +++ b/tools/gyp/test/mac/postbuild-multiple-configurations/postbuild-touch-file.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# 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. + +touch "${BUILT_PRODUCTS_DIR}/postbuild-file" diff --git a/tools/gyp/test/mac/postbuild-multiple-configurations/test.gyp b/tools/gyp/test/mac/postbuild-multiple-configurations/test.gyp new file mode 100644 index 00000000000000..c350b20d6832cf --- /dev/null +++ b/tools/gyp/test/mac/postbuild-multiple-configurations/test.gyp @@ -0,0 +1,26 @@ +# 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. +{ + 'target_defaults': { + 'configurations': { + 'Debug': {}, + 'Release': {}, + }, + }, + 'targets': [ + { + 'target_name': 'random_target', + 'type': 'executable', + 'sources': [ 'main.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'Touch a file.', + 'action': [ + './postbuild-touch-file.sh', + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/mac/postbuild-static-library/empty.c b/tools/gyp/test/mac/postbuild-static-library/empty.c new file mode 100644 index 00000000000000..9554336c0c396d --- /dev/null +++ b/tools/gyp/test/mac/postbuild-static-library/empty.c @@ -0,0 +1,4 @@ +// 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. +void f() {} diff --git a/tools/gyp/test/mac/postbuild-static-library/postbuild-touch-file.sh b/tools/gyp/test/mac/postbuild-static-library/postbuild-touch-file.sh new file mode 100644 index 00000000000000..37de4de4f6db98 --- /dev/null +++ b/tools/gyp/test/mac/postbuild-static-library/postbuild-touch-file.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# 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. + +touch "${BUILT_PRODUCTS_DIR}/$1" diff --git a/tools/gyp/test/mac/postbuild-static-library/test.gyp b/tools/gyp/test/mac/postbuild-static-library/test.gyp new file mode 100644 index 00000000000000..9ef55a0afa95f2 --- /dev/null +++ b/tools/gyp/test/mac/postbuild-static-library/test.gyp @@ -0,0 +1,34 @@ +# 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': 'my_lib', + 'type': 'static_library', + 'sources': [ 'empty.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'Postbuild that touches a file', + 'action': [ + './postbuild-touch-file.sh', 'postbuild-file' + ], + }, + ], + }, + + { + 'target_name': 'my_sourceless_lib', + 'type': 'static_library', + 'dependencies': [ 'my_lib' ], + 'postbuilds': [ + { + 'postbuild_name': 'Postbuild that touches a file', + 'action': [ + './postbuild-touch-file.sh', 'postbuild-file-sourceless' + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/mac/postbuilds/copy.sh b/tools/gyp/test/mac/postbuilds/copy.sh new file mode 100644 index 00000000000000..ecad0381db854b --- /dev/null +++ b/tools/gyp/test/mac/postbuilds/copy.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +cp "$@" diff --git a/tools/gyp/test/mac/postbuilds/file.c b/tools/gyp/test/mac/postbuilds/file.c new file mode 100644 index 00000000000000..653e71ff7ecc67 --- /dev/null +++ b/tools/gyp/test/mac/postbuilds/file.c @@ -0,0 +1,4 @@ +// 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. +void f() {} diff --git a/tools/gyp/test/mac/postbuilds/file_g.c b/tools/gyp/test/mac/postbuilds/file_g.c new file mode 100644 index 00000000000000..0f7849d2080fbc --- /dev/null +++ b/tools/gyp/test/mac/postbuilds/file_g.c @@ -0,0 +1,4 @@ +// 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. +void g() {} diff --git a/tools/gyp/test/mac/postbuilds/file_h.c b/tools/gyp/test/mac/postbuilds/file_h.c new file mode 100644 index 00000000000000..521d1f4d56d1be --- /dev/null +++ b/tools/gyp/test/mac/postbuilds/file_h.c @@ -0,0 +1,4 @@ +// 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. +void h() {} diff --git a/tools/gyp/test/mac/postbuilds/script/shared_library_postbuild.sh b/tools/gyp/test/mac/postbuilds/script/shared_library_postbuild.sh new file mode 100644 index 00000000000000..c623c8bf21870d --- /dev/null +++ b/tools/gyp/test/mac/postbuilds/script/shared_library_postbuild.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# 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. + +set -e + +lib="${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}" +nm ${lib} > /dev/null # Just make sure this works. + +pattern="${1}" + +if [ $pattern != "a|b" ]; then + echo "Parameter quoting is broken" + exit 1 +fi + +if [ "${2}" != "arg with spaces" ]; then + echo "Parameter space escaping is broken" + exit 1 +fi + +touch "${lib}"_touch diff --git a/tools/gyp/test/mac/postbuilds/script/static_library_postbuild.sh b/tools/gyp/test/mac/postbuilds/script/static_library_postbuild.sh new file mode 100644 index 00000000000000..2bf09b34e1c998 --- /dev/null +++ b/tools/gyp/test/mac/postbuilds/script/static_library_postbuild.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# 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. + +set -e + +lib="${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}" +nm ${lib} > /dev/null # Just make sure this works. + +pattern="${1}" + +if [ $pattern != "a|b" ]; then + echo "Parameter quote escaping is broken" + exit 1 +fi + +if [ "${2}" != "arg with spaces" ]; then + echo "Parameter space escaping is broken" + exit 1 +fi + +touch "${lib}"_touch.a diff --git a/tools/gyp/test/mac/postbuilds/subdirectory/copied_file.txt b/tools/gyp/test/mac/postbuilds/subdirectory/copied_file.txt new file mode 100644 index 00000000000000..a634f85b6cc452 --- /dev/null +++ b/tools/gyp/test/mac/postbuilds/subdirectory/copied_file.txt @@ -0,0 +1 @@ +This file should be copied to the products dir. diff --git a/tools/gyp/test/mac/postbuilds/subdirectory/nested_target.gyp b/tools/gyp/test/mac/postbuilds/subdirectory/nested_target.gyp new file mode 100644 index 00000000000000..6d4f2395e375b3 --- /dev/null +++ b/tools/gyp/test/mac/postbuilds/subdirectory/nested_target.gyp @@ -0,0 +1,53 @@ +# 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': 'nest_el', + 'type': 'static_library', + 'sources': [ '../file_g.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'Static library postbuild', + 'variables': { + 'some_regex': 'a|b', + }, + 'action': [ + '../script/static_library_postbuild.sh', + '<(some_regex)', + 'arg with spaces', + ], + }, + ], + }, + { + 'target_name': 'nest_dyna', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ '../file_h.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'Dynamic library postbuild', + 'variables': { + 'some_regex': 'a|b', + }, + 'action': [ + '../script/shared_library_postbuild.sh', + '<(some_regex)', + 'arg with spaces', + ], + }, + { + 'postbuild_name': 'Test paths relative to gyp file', + 'action': [ + '../copy.sh', + './copied_file.txt', + '${BUILT_PRODUCTS_DIR}/copied_file_2.txt', + ], + }, + ], + }, + ], +} + diff --git a/tools/gyp/test/mac/postbuilds/test.gyp b/tools/gyp/test/mac/postbuilds/test.gyp new file mode 100644 index 00000000000000..7c0b523f86f0e2 --- /dev/null +++ b/tools/gyp/test/mac/postbuilds/test.gyp @@ -0,0 +1,93 @@ +# 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': 'el', + 'type': 'static_library', + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'Static library postbuild', + 'variables': { + 'some_regex': 'a|b', + }, + 'action': [ + 'script/static_library_postbuild.sh', + '<(some_regex)', + 'arg with spaces', + ], + }, + { + 'postbuild_name': 'Test variable in gyp file', + 'action': [ + 'cp', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}_gyp_touch.a', + ], + }, + ], + }, + { + 'target_name': 'dyna', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'dependencies': [ + 'subdirectory/nested_target.gyp:nest_dyna', + 'subdirectory/nested_target.gyp:nest_el', + ], + 'postbuilds': [ + { + 'postbuild_name': 'Dynamic library postbuild', + 'variables': { + 'some_regex': 'a|b', + }, + 'action': [ + 'script/shared_library_postbuild.sh', + '<(some_regex)', + 'arg with spaces', + ], + }, + { + 'postbuild_name': 'Test variable in gyp file', + 'action': [ + 'cp', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}_gyp_touch', + ], + }, + { + 'postbuild_name': 'Test paths relative to gyp file', + 'action': [ + './copy.sh', + 'subdirectory/copied_file.txt', + '${BUILT_PRODUCTS_DIR}', + ], + }, + ], + }, + { + 'target_name': 'dyna_standalone', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'Test variable in gyp file', + 'action': [ + 'cp', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}_gyp_touch.dylib', + ], + }, + ], + }, + { + 'target_name': 'EmptyBundle', + 'product_extension': 'bundle', + 'type': 'executable', + 'mac_bundle': 1, + }, + ], +} diff --git a/tools/gyp/test/mac/prefixheader/file.c b/tools/gyp/test/mac/prefixheader/file.c new file mode 100644 index 00000000000000..d0b39d1f6d8bb4 --- /dev/null +++ b/tools/gyp/test/mac/prefixheader/file.c @@ -0,0 +1 @@ +MyInt f() { return 0; } diff --git a/tools/gyp/test/mac/prefixheader/file.cc b/tools/gyp/test/mac/prefixheader/file.cc new file mode 100644 index 00000000000000..d0b39d1f6d8bb4 --- /dev/null +++ b/tools/gyp/test/mac/prefixheader/file.cc @@ -0,0 +1 @@ +MyInt f() { return 0; } diff --git a/tools/gyp/test/mac/prefixheader/file.m b/tools/gyp/test/mac/prefixheader/file.m new file mode 100644 index 00000000000000..d0b39d1f6d8bb4 --- /dev/null +++ b/tools/gyp/test/mac/prefixheader/file.m @@ -0,0 +1 @@ +MyInt f() { return 0; } diff --git a/tools/gyp/test/mac/prefixheader/file.mm b/tools/gyp/test/mac/prefixheader/file.mm new file mode 100644 index 00000000000000..d0b39d1f6d8bb4 --- /dev/null +++ b/tools/gyp/test/mac/prefixheader/file.mm @@ -0,0 +1 @@ +MyInt f() { return 0; } diff --git a/tools/gyp/test/mac/prefixheader/header.h b/tools/gyp/test/mac/prefixheader/header.h new file mode 100644 index 00000000000000..0716e500c5a69d --- /dev/null +++ b/tools/gyp/test/mac/prefixheader/header.h @@ -0,0 +1 @@ +typedef int MyInt; diff --git a/tools/gyp/test/mac/prefixheader/test.gyp b/tools/gyp/test/mac/prefixheader/test.gyp new file mode 100644 index 00000000000000..7e6b1af807f258 --- /dev/null +++ b/tools/gyp/test/mac/prefixheader/test.gyp @@ -0,0 +1,82 @@ +# 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': 'prefix_header_c', + 'type': 'static_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'GCC_PREFIX_HEADER': 'header.h', + }, + }, + { + 'target_name': 'precompiled_prefix_header_c', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'GCC_PREFIX_HEADER': 'header.h', + 'GCC_PRECOMPILE_PREFIX_HEADER': 'YES', + }, + }, + + { + 'target_name': 'prefix_header_cc', + 'type': 'static_library', + 'sources': [ 'file.cc', ], + 'xcode_settings': { + 'GCC_PREFIX_HEADER': 'header.h', + }, + }, + { + 'target_name': 'precompiled_prefix_header_cc', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.cc', ], + 'xcode_settings': { + 'GCC_PREFIX_HEADER': 'header.h', + 'GCC_PRECOMPILE_PREFIX_HEADER': 'YES', + }, + }, + + { + 'target_name': 'prefix_header_m', + 'type': 'static_library', + 'sources': [ 'file.m', ], + 'xcode_settings': { + 'GCC_PREFIX_HEADER': 'header.h', + }, + }, + { + 'target_name': 'precompiled_prefix_header_m', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.m', ], + 'xcode_settings': { + 'GCC_PREFIX_HEADER': 'header.h', + 'GCC_PRECOMPILE_PREFIX_HEADER': 'YES', + }, + }, + + { + 'target_name': 'prefix_header_mm', + 'type': 'static_library', + 'sources': [ 'file.mm', ], + 'xcode_settings': { + 'GCC_PREFIX_HEADER': 'header.h', + }, + }, + { + 'target_name': 'precompiled_prefix_header_mm', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.mm', ], + 'xcode_settings': { + 'GCC_PREFIX_HEADER': 'header.h', + 'GCC_PRECOMPILE_PREFIX_HEADER': 'YES', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/rebuild/TestApp-Info.plist b/tools/gyp/test/mac/rebuild/TestApp-Info.plist new file mode 100644 index 00000000000000..98fd5152000f7b --- /dev/null +++ b/tools/gyp/test/mac/rebuild/TestApp-Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.google.${PRODUCT_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tools/gyp/test/mac/rebuild/delay-touch.sh b/tools/gyp/test/mac/rebuild/delay-touch.sh new file mode 100644 index 00000000000000..7caf105b6e05cb --- /dev/null +++ b/tools/gyp/test/mac/rebuild/delay-touch.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +set -e + +sleep 1 # mtime resolution is 1 sec on unix. +touch "$1" diff --git a/tools/gyp/test/mac/rebuild/empty.c b/tools/gyp/test/mac/rebuild/empty.c new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/mac/rebuild/main.c b/tools/gyp/test/mac/rebuild/main.c new file mode 100644 index 00000000000000..237c8ce181774d --- /dev/null +++ b/tools/gyp/test/mac/rebuild/main.c @@ -0,0 +1 @@ +int main() {} diff --git a/tools/gyp/test/mac/rebuild/test.gyp b/tools/gyp/test/mac/rebuild/test.gyp new file mode 100644 index 00000000000000..15b4e4ef2f5b95 --- /dev/null +++ b/tools/gyp/test/mac/rebuild/test.gyp @@ -0,0 +1,56 @@ +# 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': 'test_app', + 'product_name': 'Test App', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'main.c', + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'TestApp-Info.plist', + }, + }, + { + 'target_name': 'test_app_postbuilds', + 'product_name': 'Test App 2', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'main.c', + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'TestApp-Info.plist', + }, + 'postbuilds': [ + { + 'postbuild_name': 'Postbuild that touches the app binary', + 'action': [ + './delay-touch.sh', '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}', + ], + }, + ], + }, + { + 'target_name': 'test_framework_postbuilds', + 'product_name': 'Test Framework', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ + 'empty.c', + ], + 'postbuilds': [ + { + 'postbuild_name': 'Postbuild that touches the framework binary', + 'action': [ + './delay-touch.sh', '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}', + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/mac/rpath/file.c b/tools/gyp/test/mac/rpath/file.c new file mode 100644 index 00000000000000..56757a701bf5cf --- /dev/null +++ b/tools/gyp/test/mac/rpath/file.c @@ -0,0 +1 @@ +void f() {} diff --git a/tools/gyp/test/mac/rpath/main.c b/tools/gyp/test/mac/rpath/main.c new file mode 100644 index 00000000000000..237c8ce181774d --- /dev/null +++ b/tools/gyp/test/mac/rpath/main.c @@ -0,0 +1 @@ +int main() {} diff --git a/tools/gyp/test/mac/rpath/test.gyp b/tools/gyp/test/mac/rpath/test.gyp new file mode 100644 index 00000000000000..7255cb7cd20b0a --- /dev/null +++ b/tools/gyp/test/mac/rpath/test.gyp @@ -0,0 +1,48 @@ +# 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': 'default_rpath', + 'type': 'shared_library', + 'sources': [ 'file.c' ], + }, + { + 'target_name': 'explicit_rpath', + 'type': 'shared_library', + 'sources': [ 'file.c' ], + 'xcode_settings': { + 'LD_RUNPATH_SEARCH_PATHS': ['@executable_path/.'], + }, + }, + { + 'target_name': 'explicit_rpaths_escaped', + 'type': 'shared_library', + 'sources': [ 'file.c' ], + 'xcode_settings': { + # Xcode requires spaces to be escaped, else it ends up adding two + # independent rpaths. + 'LD_RUNPATH_SEARCH_PATHS': ['First\\ rpath', 'Second\\ rpath'], + }, + }, + { + 'target_name': 'explicit_rpaths_bundle', + 'product_name': 'My Framework', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.c' ], + 'xcode_settings': { + 'LD_RUNPATH_SEARCH_PATHS': ['@loader_path/.'], + }, + }, + { + 'target_name': 'executable', + 'type': 'executable', + 'sources': [ 'main.c' ], + 'xcode_settings': { + 'LD_RUNPATH_SEARCH_PATHS': ['@executable_path/.'], + }, + }, + ], +} diff --git a/tools/gyp/test/mac/sdkroot/file.cc b/tools/gyp/test/mac/sdkroot/file.cc new file mode 100644 index 00000000000000..13ae9710402af2 --- /dev/null +++ b/tools/gyp/test/mac/sdkroot/file.cc @@ -0,0 +1,5 @@ +#include +using std::map; + +int main() { +} diff --git a/tools/gyp/test/mac/sdkroot/test.gyp b/tools/gyp/test/mac/sdkroot/test.gyp new file mode 100644 index 00000000000000..2fc11a0280b389 --- /dev/null +++ b/tools/gyp/test/mac/sdkroot/test.gyp @@ -0,0 +1,35 @@ +# 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': 'mytarget', + 'type': 'executable', + 'sources': [ 'file.cc', ], + 'xcode_settings': { + 'SDKROOT': 'macosx%s', + }, + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_shorthand.sh', ], + }, + ], + }, + { + 'target_name': 'absolute', + 'type': 'executable', + 'sources': [ 'file.cc', ], + 'xcode_settings': { + 'SDKROOT': '<(sdk_path)', + }, + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_shorthand.sh', ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/mac/sdkroot/test_shorthand.sh b/tools/gyp/test/mac/sdkroot/test_shorthand.sh new file mode 100644 index 00000000000000..ac4ac229aeefa1 --- /dev/null +++ b/tools/gyp/test/mac/sdkroot/test_shorthand.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# 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. + +set -e + +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 --git a/tools/gyp/test/mac/sourceless-module/empty.c b/tools/gyp/test/mac/sourceless-module/empty.c new file mode 100644 index 00000000000000..237c8ce181774d --- /dev/null +++ b/tools/gyp/test/mac/sourceless-module/empty.c @@ -0,0 +1 @@ +int main() {} diff --git a/tools/gyp/test/mac/sourceless-module/empty.txt b/tools/gyp/test/mac/sourceless-module/empty.txt new file mode 100644 index 00000000000000..139597f9cb07c5 --- /dev/null +++ b/tools/gyp/test/mac/sourceless-module/empty.txt @@ -0,0 +1,2 @@ + + diff --git a/tools/gyp/test/mac/sourceless-module/fun.c b/tools/gyp/test/mac/sourceless-module/fun.c new file mode 100644 index 00000000000000..d64ff8ca23dbf9 --- /dev/null +++ b/tools/gyp/test/mac/sourceless-module/fun.c @@ -0,0 +1 @@ +int f() { return 42; } diff --git a/tools/gyp/test/mac/sourceless-module/test.gyp b/tools/gyp/test/mac/sourceless-module/test.gyp new file mode 100644 index 00000000000000..cbbe63df02df38 --- /dev/null +++ b/tools/gyp/test/mac/sourceless-module/test.gyp @@ -0,0 +1,96 @@ +# 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': 'empty_bundle', + 'type': 'loadable_module', + 'mac_bundle': 1, + }, + { + 'target_name': 'resource_bundle', + 'type': 'loadable_module', + 'mac_bundle': 1, + 'actions': [ + { + 'action_name': 'Add Resource', + 'inputs': [], + 'outputs': [ + '<(INTERMEDIATE_DIR)/app_manifest/foo.manifest', + ], + 'action': [ + 'touch', '<(INTERMEDIATE_DIR)/app_manifest/foo.manifest', + ], + 'process_outputs_as_mac_bundle_resources': 1, + }, + ], + }, + { + 'target_name': 'dependent_on_resource_bundle', + 'type': 'executable', + 'sources': [ 'empty.c' ], + 'dependencies': [ + 'resource_bundle', + ], + }, + + { + 'target_name': 'alib', + 'type': 'static_library', + 'sources': [ 'fun.c' ] + }, + { # No sources, but depends on a static_library so must be linked. + 'target_name': 'resource_framework', + 'type': 'shared_library', + 'mac_bundle': 1, + 'dependencies': [ + 'alib', + ], + 'actions': [ + { + 'action_name': 'Add Resource', + 'inputs': [], + 'outputs': [ + '<(INTERMEDIATE_DIR)/app_manifest/foo.manifest', + ], + 'action': [ + 'touch', '<(INTERMEDIATE_DIR)/app_manifest/foo.manifest', + ], + 'process_outputs_as_mac_bundle_resources': 1, + }, + ], + }, + { + 'target_name': 'dependent_on_resource_framework', + 'type': 'executable', + 'sources': [ 'empty.c' ], + 'dependencies': [ + 'resource_framework', + ], + }, + + { # No actions, but still have resources. + 'target_name': 'mac_resource_bundle_no_actions', + 'product_extension': 'bundle', + 'type': 'executable', + 'mac_bundle': 1, + 'mac_bundle_resources': [ + 'empty.txt', + ], + }, + { + 'target_name': 'bundle_dependent_on_resource_bundle_no_actions', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ 'empty.c' ], + 'dependencies': [ + 'mac_resource_bundle_no_actions', + ], + 'mac_bundle_resources': [ + '<(PRODUCT_DIR)/mac_resource_bundle_no_actions.bundle', + ], + }, + ], +} + diff --git a/tools/gyp/test/mac/strip/file.c b/tools/gyp/test/mac/strip/file.c new file mode 100644 index 00000000000000..a4c504de7170cc --- /dev/null +++ b/tools/gyp/test/mac/strip/file.c @@ -0,0 +1,22 @@ +// 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. + +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 --git a/tools/gyp/test/mac/strip/main.c b/tools/gyp/test/mac/strip/main.c new file mode 100644 index 00000000000000..b2291a6b09ecd3 --- /dev/null +++ b/tools/gyp/test/mac/strip/main.c @@ -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 --git a/tools/gyp/test/mac/strip/strip.saves b/tools/gyp/test/mac/strip/strip.saves new file mode 100644 index 00000000000000..b60ca62857a217 --- /dev/null +++ b/tools/gyp/test/mac/strip/strip.saves @@ -0,0 +1,5 @@ +# Copyright (c) 2011 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 file would list symbols that should not be stripped. diff --git a/tools/gyp/test/mac/strip/subdirectory/nested_file.c b/tools/gyp/test/mac/strip/subdirectory/nested_file.c new file mode 100644 index 00000000000000..50daa6c13b49e7 --- /dev/null +++ b/tools/gyp/test/mac/strip/subdirectory/nested_file.c @@ -0,0 +1 @@ +void nested_f() {} diff --git a/tools/gyp/test/mac/strip/subdirectory/nested_strip.saves b/tools/gyp/test/mac/strip/subdirectory/nested_strip.saves new file mode 100644 index 00000000000000..d434c0ef458870 --- /dev/null +++ b/tools/gyp/test/mac/strip/subdirectory/nested_strip.saves @@ -0,0 +1,5 @@ +# 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. + +# This file would list symbols that should not be stripped. diff --git a/tools/gyp/test/mac/strip/subdirectory/subdirectory.gyp b/tools/gyp/test/mac/strip/subdirectory/subdirectory.gyp new file mode 100644 index 00000000000000..5d0d190914e556 --- /dev/null +++ b/tools/gyp/test/mac/strip/subdirectory/subdirectory.gyp @@ -0,0 +1,38 @@ +# 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': 'nested_strip_save', + 'type': 'shared_library', + 'sources': [ 'nested_file.c', ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + 'STRIPFLAGS': '-s $(CHROMIUM_STRIP_SAVE_FILE)', + 'CHROMIUM_STRIP_SAVE_FILE': 'nested_strip.saves', + }, + }, + { + 'target_name': 'nested_strip_save_postbuild', + 'type': 'shared_library', + 'sources': [ 'nested_file.c', ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + 'STRIPFLAGS': '-s $(CHROMIUM_STRIP_SAVE_FILE)', + 'CHROMIUM_STRIP_SAVE_FILE': 'nested_strip.saves', + }, + 'postbuilds': [ + { + 'postbuild_name': 'Action that reads CHROMIUM_STRIP_SAVE_FILE', + 'action': [ + './test_reading_save_file_from_postbuild.sh', + ], + }, + ], + }, + ], +} + diff --git a/tools/gyp/test/mac/strip/subdirectory/test_reading_save_file_from_postbuild.sh b/tools/gyp/test/mac/strip/subdirectory/test_reading_save_file_from_postbuild.sh new file mode 100644 index 00000000000000..976943680ee9a9 --- /dev/null +++ b/tools/gyp/test/mac/strip/subdirectory/test_reading_save_file_from_postbuild.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +set -e + +test -f ${CHROMIUM_STRIP_SAVE_FILE} diff --git a/tools/gyp/test/mac/strip/test-defaults.gyp b/tools/gyp/test/mac/strip/test-defaults.gyp new file mode 100644 index 00000000000000..e688b955a742f0 --- /dev/null +++ b/tools/gyp/test/mac/strip/test-defaults.gyp @@ -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 --git a/tools/gyp/test/mac/strip/test.gyp b/tools/gyp/test/mac/strip/test.gyp new file mode 100644 index 00000000000000..2558aa91bbe954 --- /dev/null +++ b/tools/gyp/test/mac/strip/test.gyp @@ -0,0 +1,119 @@ +# 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 xcode_settings affect stripping: +# "Deployment postprocessing involves stripping the binary, and setting +# its file mode, owner, and group." +#'DEPLOYMENT_POSTPROCESSING': 'YES', + +# "Specifies whether to strip symbol information from the binary. +# Prerequisite: $DEPLOYMENT_POSTPROCESSING = YES" "Default Value: 'NO'" +#'STRIP_INSTALLED_PRODUCT': 'YES', + +# "Values: +# * all: Strips the binary completely, removing the symbol table and +# relocation information +# * non-global: Strips nonglobal symbols but saves external symbols. +# * debugging: Strips debugging symbols but saves local and global +# symbols." +# (maps to no flag, -x, -S in that order) +#'STRIP_STYLE': 'non-global', + +# "Additional strip flags" +#'STRIPFLAGS': '-c', + +# "YES: Copied binaries are stripped of debugging symbols. This does +# not cause the binary produced by the linker to be stripped. Use +# 'STRIP_INSTALLED_PRODUCT (Strip Linked Product)' to have the linker +# strip the binary." +#'COPY_PHASE_STRIP': 'NO', +{ + 'targets': [ + { + 'target_name': 'no_postprocess', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'NO', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + { + 'target_name': 'no_strip', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'NO', + }, + }, + { + 'target_name': 'strip_all', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + 'STRIP_STYLE': 'all', + }, + }, + { + 'target_name': 'strip_nonglobal', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + 'STRIP_STYLE': 'non-global', + }, + }, + { + 'target_name': 'strip_debugging', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + 'STRIP_STYLE': 'debugging', + }, + }, + { + 'target_name': 'strip_all_custom_flags', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + 'STRIP_STYLE': 'all', + 'STRIPFLAGS': '-c', + }, + }, + { + 'target_name': 'strip_all_bundle', + 'type': 'shared_library', + 'mac_bundle': '1', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + 'STRIP_STYLE': 'all', + }, + }, + { + 'target_name': 'strip_save', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'dependencies': [ + 'subdirectory/subdirectory.gyp:nested_strip_save', + 'subdirectory/subdirectory.gyp:nested_strip_save_postbuild', + ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + 'STRIPFLAGS': '-s $(CHROMIUM_STRIP_SAVE_FILE)', + 'CHROMIUM_STRIP_SAVE_FILE': 'strip.saves', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/swift-library/Info.plist b/tools/gyp/test/mac/swift-library/Info.plist new file mode 100644 index 00000000000000..804990ca5e8062 --- /dev/null +++ b/tools/gyp/test/mac/swift-library/Info.plist @@ -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 --git a/tools/gyp/test/mac/swift-library/file.swift b/tools/gyp/test/mac/swift-library/file.swift new file mode 100644 index 00000000000000..88db7da5c6cb10 --- /dev/null +++ b/tools/gyp/test/mac/swift-library/file.swift @@ -0,0 +1,9 @@ +import Foundation + +public class GypSwiftTest { + let myProperty = false + + init() { + self.myProperty = true + } +} \ No newline at end of file diff --git a/tools/gyp/test/mac/swift-library/test.gyp b/tools/gyp/test/mac/swift-library/test.gyp new file mode 100644 index 00000000000000..373a677cbd86d6 --- /dev/null +++ b/tools/gyp/test/mac/swift-library/test.gyp @@ -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 --git a/tools/gyp/test/mac/type_envvars/file.c b/tools/gyp/test/mac/type_envvars/file.c new file mode 100644 index 00000000000000..9cddaf1b0b401b --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/file.c @@ -0,0 +1,6 @@ +// 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. + +void f() {} +int main() {} diff --git a/tools/gyp/test/mac/type_envvars/test.gyp b/tools/gyp/test/mac/type_envvars/test.gyp new file mode 100644 index 00000000000000..465670056bde38 --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test.gyp @@ -0,0 +1,100 @@ +# 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': 'my_app', + 'product_name': 'My App', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_bundle_executable.sh', ], + }, + ], + }, + { + 'target_name': 'bundle_loadable_module', + 'type': 'loadable_module', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_bundle_loadable_module.sh', ], + }, + ], + }, + { + 'target_name': 'bundle_shared_library', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_bundle_shared_library.sh', ], + }, + ], + }, + # Types 'static_library' and 'none' can't exist as bundles. + + { + 'target_name': 'nonbundle_executable', + 'type': 'executable', + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_nonbundle_executable.sh', ], + }, + ], + }, + { + 'target_name': 'nonbundle_loadable_module', + 'type': 'loadable_module', + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_nonbundle_loadable_module.sh', ], + }, + ], + }, + { + 'target_name': 'nonbundle_shared_library', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_nonbundle_shared_library.sh', ], + }, + ], + }, + { + 'target_name': 'nonbundle_static_library', + 'type': 'static_library', + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_nonbundle_static_library.sh', ], + }, + ], + }, + { + 'target_name': 'nonbundle_none', + 'type': 'none', + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_nonbundle_none.sh', ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/mac/type_envvars/test_bundle_executable.sh b/tools/gyp/test/mac/type_envvars/test_bundle_executable.sh new file mode 100644 index 00000000000000..9a08c8f0ccae9e --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test_bundle_executable.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# 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. + +set -e + +test $MACH_O_TYPE = mh_execute +test $PRODUCT_TYPE = com.apple.product-type.application +test "${PRODUCT_NAME}" = "My App" +test "${FULL_PRODUCT_NAME}" = "My App.app" + +test "${EXECUTABLE_NAME}" = "My App" +test "${EXECUTABLE_PATH}" = "My App.app/Contents/MacOS/My App" +test "${WRAPPER_NAME}" = "My App.app" + +test "${CONTENTS_FOLDER_PATH}" = "My App.app/Contents" +test "${EXECUTABLE_FOLDER_PATH}" = "My App.app/Contents/MacOS" +test "${UNLOCALIZED_RESOURCES_FOLDER_PATH}" = "My App.app/Contents/Resources" +test "${JAVA_FOLDER_PATH}" = "My App.app/Contents/Resources/Java" +test "${FRAMEWORKS_FOLDER_PATH}" = "My App.app/Contents/Frameworks" +test "${SHARED_FRAMEWORKS_FOLDER_PATH}" = "My App.app/Contents/SharedFrameworks" +test "${SHARED_SUPPORT_FOLDER_PATH}" = "My App.app/Contents/SharedSupport" +test "${PLUGINS_FOLDER_PATH}" = "My App.app/Contents/PlugIns" +test "${XPCSERVICES_FOLDER_PATH}" = "My App.app/Contents/XPCServices" + +[[ ! $DYLIB_INSTALL_NAME_BASE && ${DYLIB_INSTALL_NAME_BASE-_} ]] +[[ ! $LD_DYLIB_INSTALL_NAME && ${LD_DYLIB_INSTALL_NAME-_} ]] + +"$(dirname "$0")/test_check_sdkroot.sh" diff --git a/tools/gyp/test/mac/type_envvars/test_bundle_loadable_module.sh b/tools/gyp/test/mac/type_envvars/test_bundle_loadable_module.sh new file mode 100644 index 00000000000000..b5c7638293b2f6 --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test_bundle_loadable_module.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# 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. + +set -e + +test $MACH_O_TYPE = mh_bundle +test $PRODUCT_TYPE = com.apple.product-type.bundle +test $PRODUCT_NAME = bundle_loadable_module +test $FULL_PRODUCT_NAME = bundle_loadable_module.bundle + +test $EXECUTABLE_NAME = bundle_loadable_module +test $EXECUTABLE_PATH = \ + "bundle_loadable_module.bundle/Contents/MacOS/bundle_loadable_module" +test $WRAPPER_NAME = bundle_loadable_module.bundle + +test $CONTENTS_FOLDER_PATH = bundle_loadable_module.bundle/Contents +test $EXECUTABLE_FOLDER_PATH = bundle_loadable_module.bundle/Contents/MacOS +test $UNLOCALIZED_RESOURCES_FOLDER_PATH = \ + bundle_loadable_module.bundle/Contents/Resources +test $JAVA_FOLDER_PATH = bundle_loadable_module.bundle/Contents/Resources/Java +test $FRAMEWORKS_FOLDER_PATH = bundle_loadable_module.bundle/Contents/Frameworks +test $SHARED_FRAMEWORKS_FOLDER_PATH = \ + bundle_loadable_module.bundle/Contents/SharedFrameworks +test $SHARED_SUPPORT_FOLDER_PATH = \ + bundle_loadable_module.bundle/Contents/SharedSupport +test $PLUGINS_FOLDER_PATH = bundle_loadable_module.bundle/Contents/PlugIns +test $XPCSERVICES_FOLDER_PATH = \ + bundle_loadable_module.bundle/Contents/XPCServices + +[[ ! $DYLIB_INSTALL_NAME_BASE && ${DYLIB_INSTALL_NAME_BASE-_} ]] +[[ ! $LD_DYLIB_INSTALL_NAME && ${LD_DYLIB_INSTALL_NAME-_} ]] + +"$(dirname "$0")/test_check_sdkroot.sh" diff --git a/tools/gyp/test/mac/type_envvars/test_bundle_shared_library.sh b/tools/gyp/test/mac/type_envvars/test_bundle_shared_library.sh new file mode 100644 index 00000000000000..9c2dc0626f5b6e --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test_bundle_shared_library.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# 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. + +set -e + +test $MACH_O_TYPE = mh_dylib +test $PRODUCT_TYPE = com.apple.product-type.framework +test $PRODUCT_NAME = bundle_shared_library +test $FULL_PRODUCT_NAME = bundle_shared_library.framework + +test $EXECUTABLE_NAME = bundle_shared_library +test $EXECUTABLE_PATH = \ + "bundle_shared_library.framework/Versions/A/bundle_shared_library" +test $WRAPPER_NAME = bundle_shared_library.framework + +test $CONTENTS_FOLDER_PATH = bundle_shared_library.framework/Versions/A +test $EXECUTABLE_FOLDER_PATH = bundle_shared_library.framework/Versions/A +test $UNLOCALIZED_RESOURCES_FOLDER_PATH = \ + bundle_shared_library.framework/Versions/A/Resources +test $JAVA_FOLDER_PATH = \ + bundle_shared_library.framework/Versions/A/Resources/Java +test $FRAMEWORKS_FOLDER_PATH = \ + bundle_shared_library.framework/Versions/A/Frameworks +test $SHARED_FRAMEWORKS_FOLDER_PATH = \ + bundle_shared_library.framework/Versions/A/SharedFrameworks +test $SHARED_SUPPORT_FOLDER_PATH = \ + bundle_shared_library.framework/Versions/A/Resources +test $PLUGINS_FOLDER_PATH = bundle_shared_library.framework/Versions/A/PlugIns +test $XPCSERVICES_FOLDER_PATH = \ + bundle_shared_library.framework/Versions/A/XPCServices + +test $DYLIB_INSTALL_NAME_BASE = "/Library/Frameworks" +test $LD_DYLIB_INSTALL_NAME = \ + "/Library/Frameworks/bundle_shared_library.framework/Versions/A/bundle_shared_library" + +"$(dirname "$0")/test_check_sdkroot.sh" diff --git a/tools/gyp/test/mac/type_envvars/test_check_sdkroot.sh b/tools/gyp/test/mac/type_envvars/test_check_sdkroot.sh new file mode 100644 index 00000000000000..1297dbeff11bbb --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test_check_sdkroot.sh @@ -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 --git a/tools/gyp/test/mac/type_envvars/test_nonbundle_executable.sh b/tools/gyp/test/mac/type_envvars/test_nonbundle_executable.sh new file mode 100644 index 00000000000000..9fbbd95b8dd99f --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test_nonbundle_executable.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# 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. + +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-_} ]] +test $PRODUCT_TYPE = com.apple.product-type.tool +test $PRODUCT_NAME = nonbundle_executable +test $FULL_PRODUCT_NAME = nonbundle_executable + +test $EXECUTABLE_NAME = nonbundle_executable +test $EXECUTABLE_PATH = nonbundle_executable +[[ ! $WRAPPER_NAME && ${WRAPPER_NAME-_} ]] + +[[ ! $CONTENTS_FOLDER_PATH && ${CONTENTS_FOLDER_PATH-_} ]] +[[ ! $EXECUTABLE_FOLDER_PATH && ${EXECUTABLE_FOLDER_PATH-_} ]] +[[ ! $UNLOCALIZED_RESOURCES_FOLDER_PATH \ + && ${UNLOCALIZED_RESOURCES_FOLDER_PATH-_} ]] +[[ ! $JAVA_FOLDER_PATH && ${JAVA_FOLDER_PATH-_} ]] +[[ ! $FRAMEWORKS_FOLDER_PATH && ${FRAMEWORKS_FOLDER_PATH-_} ]] +[[ ! $SHARED_FRAMEWORKS_FOLDER_PATH && ${SHARED_FRAMEWORKS_FOLDER_PATH-_} ]] +[[ ! $SHARED_SUPPORT_FOLDER_PATH && ${SHARED_SUPPORT_FOLDER_PATH-_} ]] +[[ ! $PLUGINS_FOLDER_PATH && ${PLUGINS_FOLDER_PATH-_} ]] +[[ ! $XPCSERVICES_FOLDER_PATH && ${XPCSERVICES_FOLDER_PATH-_} ]] + +[[ ! $DYLIB_INSTALL_NAME_BASE && ${DYLIB_INSTALL_NAME_BASE-_} ]] +[[ ! $LD_DYLIB_INSTALL_NAME && ${LD_DYLIB_INSTALL_NAME-_} ]] + +"$(dirname "$0")/test_check_sdkroot.sh" diff --git a/tools/gyp/test/mac/type_envvars/test_nonbundle_loadable_module.sh b/tools/gyp/test/mac/type_envvars/test_nonbundle_loadable_module.sh new file mode 100644 index 00000000000000..b4c3ba976ef266 --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test_nonbundle_loadable_module.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# 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. + +set -e + +test $MACH_O_TYPE = mh_bundle +test $PRODUCT_TYPE = com.apple.product-type.library.dynamic +test $PRODUCT_NAME = nonbundle_loadable_module +test $FULL_PRODUCT_NAME = nonbundle_loadable_module.so + +test $EXECUTABLE_NAME = nonbundle_loadable_module.so +test $EXECUTABLE_PATH = nonbundle_loadable_module.so +[[ ! $WRAPPER_NAME && ${WRAPPER_NAME-_} ]] + +[[ ! $CONTENTS_FOLDER_PATH && ${CONTENTS_FOLDER_PATH-_} ]] +[[ ! $EXECUTABLE_FOLDER_PATH && ${EXECUTABLE_FOLDER_PATH-_} ]] +[[ ! $UNLOCALIZED_RESOURCES_FOLDER_PATH \ + && ${UNLOCALIZED_RESOURCES_FOLDER_PATH-_} ]] +[[ ! $JAVA_FOLDER_PATH && ${JAVA_FOLDER_PATH-_} ]] +[[ ! $FRAMEWORKS_FOLDER_PATH && ${FRAMEWORKS_FOLDER_PATH-_} ]] +[[ ! $SHARED_FRAMEWORKS_FOLDER_PATH && ${SHARED_FRAMEWORKS_FOLDER_PATH-_} ]] +[[ ! $SHARED_SUPPORT_FOLDER_PATH && ${SHARED_SUPPORT_FOLDER_PATH-_} ]] +[[ ! $PLUGINS_FOLDER_PATH && ${PLUGINS_FOLDER_PATH-_} ]] +[[ ! $XPCSERVICES_FOLDER_PATH && ${XPCSERVICES_FOLDER_PATH-_} ]] + +test $DYLIB_INSTALL_NAME_BASE = "/usr/local/lib" +test $LD_DYLIB_INSTALL_NAME = "/usr/local/lib/nonbundle_loadable_module.so" + +"$(dirname "$0")/test_check_sdkroot.sh" diff --git a/tools/gyp/test/mac/type_envvars/test_nonbundle_none.sh b/tools/gyp/test/mac/type_envvars/test_nonbundle_none.sh new file mode 100644 index 00000000000000..e2dc7fd9cd56e6 --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test_nonbundle_none.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# 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. + +set -e + +# Check for "not set", not just "empty": +[[ ! $MACH_O_TYPE && ${MACH_O_TYPE-_} ]] +[[ ! $PRODUCT_TYPE && ${PRODUCT_TYPE-_} ]] +test $PRODUCT_NAME = nonbundle_none +[[ ! $FULL_PRODUCT_NAME && ${FULL_PRODUCT_NAME-_} ]] + +[[ ! $EXECUTABLE_NAME && ${EXECUTABLE_NAME-_} ]] +[[ ! $EXECUTABLE_PATH && ${EXECUTABLE_PATH-_} ]] +[[ ! $WRAPPER_NAME && ${WRAPPER_NAME-_} ]] + +[[ ! $CONTENTS_FOLDER_PATH && ${CONTENTS_FOLDER_PATH-_} ]] +[[ ! $EXECUTABLE_FOLDER_PATH && ${EXECUTABLE_FOLDER_PATH-_} ]] +[[ ! $UNLOCALIZED_RESOURCES_FOLDER_PATH \ + && ${UNLOCALIZED_RESOURCES_FOLDER_PATH-_} ]] +[[ ! $JAVA_FOLDER_PATH && ${JAVA_FOLDER_PATH-_} ]] +[[ ! $FRAMEWORKS_FOLDER_PATH && ${FRAMEWORKS_FOLDER_PATH-_} ]] +[[ ! $SHARED_FRAMEWORKS_FOLDER_PATH && ${SHARED_FRAMEWORKS_FOLDER_PATH-_} ]] +[[ ! $SHARED_SUPPORT_FOLDER_PATH && ${SHARED_SUPPORT_FOLDER_PATH-_} ]] +[[ ! $PLUGINS_FOLDER_PATH && ${PLUGINS_FOLDER_PATH-_} ]] +[[ ! $XPCSERVICES_FOLDER_PATH && ${XPCSERVICES_FOLDER_PATH-_} ]] + +[[ ! $DYLIB_INSTALL_NAME_BASE && ${DYLIB_INSTALL_NAME_BASE-_} ]] +[[ ! $LD_DYLIB_INSTALL_NAME && ${LD_DYLIB_INSTALL_NAME-_} ]] + +"$(dirname "$0")/test_check_sdkroot.sh" diff --git a/tools/gyp/test/mac/type_envvars/test_nonbundle_shared_library.sh b/tools/gyp/test/mac/type_envvars/test_nonbundle_shared_library.sh new file mode 100644 index 00000000000000..ba63ec1a48fa98 --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test_nonbundle_shared_library.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# 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. + +set -e + +test $MACH_O_TYPE = mh_dylib +test $PRODUCT_TYPE = com.apple.product-type.library.dynamic +test $PRODUCT_NAME = nonbundle_shared_library +test $FULL_PRODUCT_NAME = libnonbundle_shared_library.dylib + +test $EXECUTABLE_NAME = libnonbundle_shared_library.dylib +test $EXECUTABLE_PATH = libnonbundle_shared_library.dylib +[[ ! $WRAPPER_NAME && ${WRAPPER_NAME-_} ]] + +[[ ! $CONTENTS_FOLDER_PATH && ${CONTENTS_FOLDER_PATH-_} ]] +[[ ! $EXECUTABLE_FOLDER_PATH && ${EXECUTABLE_FOLDER_PATH-_} ]] +[[ ! $UNLOCALIZED_RESOURCES_FOLDER_PATH && \ + ${UNLOCALIZED_RESOURCES_FOLDER_PATH-_} ]] +[[ ! $JAVA_FOLDER_PATH && ${JAVA_FOLDER_PATH-_} ]] +[[ ! $FRAMEWORKS_FOLDER_PATH && ${FRAMEWORKS_FOLDER_PATH-_} ]] +[[ ! $SHARED_FRAMEWORKS_FOLDER_PATH && ${SHARED_FRAMEWORKS_FOLDER_PATH-_} ]] +[[ ! $SHARED_SUPPORT_FOLDER_PATH && ${SHARED_SUPPORT_FOLDER_PATH-_} ]] +[[ ! $PLUGINS_FOLDER_PATH && ${PLUGINS_FOLDER_PATH-_} ]] +[[ ! $XPCSERVICES_FOLDER_PATH && ${XPCSERVICES_FOLDER_PATH-_} ]] + +test $DYLIB_INSTALL_NAME_BASE = "/usr/local/lib" +test $LD_DYLIB_INSTALL_NAME = "/usr/local/lib/libnonbundle_shared_library.dylib" + +"$(dirname "$0")/test_check_sdkroot.sh" diff --git a/tools/gyp/test/mac/type_envvars/test_nonbundle_static_library.sh b/tools/gyp/test/mac/type_envvars/test_nonbundle_static_library.sh new file mode 100644 index 00000000000000..63aac57b0b3460 --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test_nonbundle_static_library.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# 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. + +set -e + +test $MACH_O_TYPE = staticlib +test $PRODUCT_TYPE = com.apple.product-type.library.static +test $PRODUCT_NAME = nonbundle_static_library +test $FULL_PRODUCT_NAME = libnonbundle_static_library.a + +test $EXECUTABLE_NAME = libnonbundle_static_library.a +test $EXECUTABLE_PATH = libnonbundle_static_library.a +[[ ! $WRAPPER_NAME && ${WRAPPER_NAME-_} ]] + +[[ ! $CONTENTS_FOLDER_PATH && ${CONTENTS_FOLDER_PATH-_} ]] +[[ ! $EXECUTABLE_FOLDER_PATH && ${EXECUTABLE_FOLDER_PATH-_} ]] +[[ ! $UNLOCALIZED_RESOURCES_FOLDER_PATH && \ + ${UNLOCALIZED_RESOURCES_FOLDER_PATH-_} ]] +[[ ! $JAVA_FOLDER_PATH && ${JAVA_FOLDER_PATH-_} ]] +[[ ! $FRAMEWORKS_FOLDER_PATH && ${FRAMEWORKS_FOLDER_PATH-_} ]] +[[ ! $SHARED_FRAMEWORKS_FOLDER_PATH && ${SHARED_FRAMEWORKS_FOLDER_PATH-_} ]] +[[ ! $SHARED_SUPPORT_FOLDER_PATH && ${SHARED_SUPPORT_FOLDER_PATH-_} ]] +[[ ! $PLUGINS_FOLDER_PATH && ${PLUGINS_FOLDER_PATH-_} ]] +[[ ! $XPCSERVICES_FOLDER_PATH && ${XPCSERVICES_FOLDER_PATH-_} ]] + +[[ ! $DYLIB_INSTALL_NAME_BASE && ${DYLIB_INSTALL_NAME_BASE-_} ]] +[[ ! $LD_DYLIB_INSTALL_NAME && ${LD_DYLIB_INSTALL_NAME-_} ]] + +"$(dirname "$0")/test_check_sdkroot.sh" diff --git a/tools/gyp/test/mac/unicode-settings/file.cc b/tools/gyp/test/mac/unicode-settings/file.cc new file mode 100644 index 00000000000000..b2f997621bea95 --- /dev/null +++ b/tools/gyp/test/mac/unicode-settings/file.cc @@ -0,0 +1,2 @@ +int main() { +} diff --git a/tools/gyp/test/mac/unicode-settings/test.gyp b/tools/gyp/test/mac/unicode-settings/test.gyp new file mode 100644 index 00000000000000..b331ae453f1954 --- /dev/null +++ b/tools/gyp/test/mac/unicode-settings/test.gyp @@ -0,0 +1,23 @@ +# 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': 'myapp', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ 'file.cc', ], + 'xcode_settings': { + 'BUNDLE_DISPLAY_NAME': 'α\011', + }, + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_bundle_display_name.sh', ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/mac/unicode-settings/test_bundle_display_name.sh b/tools/gyp/test/mac/unicode-settings/test_bundle_display_name.sh new file mode 100644 index 00000000000000..95dd6267a33d02 --- /dev/null +++ b/tools/gyp/test/mac/unicode-settings/test_bundle_display_name.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# 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. + +test "${BUNDLE_DISPLAY_NAME}" = 'α ' diff --git a/tools/gyp/test/mac/xcode-env-order/Info.plist b/tools/gyp/test/mac/xcode-env-order/Info.plist new file mode 100644 index 00000000000000..e11f21e52d13c4 --- /dev/null +++ b/tools/gyp/test/mac/xcode-env-order/Info.plist @@ -0,0 +1,56 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.google.${PRODUCT_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + BraceProcessedKey1 + ${BRACE_DEPENDENT_KEY1} + BraceProcessedKey2 + ${BRACE_DEPENDENT_KEY2} + BraceProcessedKey3 + ${BRACE_DEPENDENT_KEY3} + + ParenProcessedKey1 + ${PAREN_DEPENDENT_KEY1} + ParenProcessedKey2 + ${PAREN_DEPENDENT_KEY2} + ParenProcessedKey3 + ${PAREN_DEPENDENT_KEY3} + + BareProcessedKey1 + ${BARE_DEPENDENT_KEY1} + BareProcessedKey2 + ${BARE_DEPENDENT_KEY2} + BareProcessedKey3 + ${BARE_DEPENDENT_KEY3} + + MixedProcessedKey + ${MIXED_DEPENDENT_KEY} + + diff --git a/tools/gyp/test/mac/xcode-env-order/file.ext1 b/tools/gyp/test/mac/xcode-env-order/file.ext1 new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/mac/xcode-env-order/file.ext2 b/tools/gyp/test/mac/xcode-env-order/file.ext2 new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/mac/xcode-env-order/file.ext3 b/tools/gyp/test/mac/xcode-env-order/file.ext3 new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/mac/xcode-env-order/main.c b/tools/gyp/test/mac/xcode-env-order/main.c new file mode 100644 index 00000000000000..1bf4b2a11abd99 --- /dev/null +++ b/tools/gyp/test/mac/xcode-env-order/main.c @@ -0,0 +1,7 @@ +// 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. + +int main() { + return 0; +} diff --git a/tools/gyp/test/mac/xcode-env-order/test.gyp b/tools/gyp/test/mac/xcode-env-order/test.gyp new file mode 100644 index 00000000000000..8f975f7d6b17fe --- /dev/null +++ b/tools/gyp/test/mac/xcode-env-order/test.gyp @@ -0,0 +1,121 @@ +# 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_app', + 'product_name': 'Test', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'main.c', + 'file.ext1', + 'file.ext2', + 'file.ext3', + ], + # Env vars in copies. + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/${PRODUCT_NAME}-copy-brace', + 'files': [ 'main.c', ], # ${SOURCE_ROOT} doesn't work with xcode + }, + { + 'destination': '<(PRODUCT_DIR)/$(PRODUCT_NAME)-copy-paren', + 'files': [ '$(SOURCE_ROOT)/main.c', ], + }, + { + 'destination': '<(PRODUCT_DIR)/$PRODUCT_NAME-copy-bare', + 'files': [ 'main.c', ], # $SOURCE_ROOT doesn't work with xcode + }, + ], + # Env vars in actions. The $FOO's are here to test that env vars that + # aren't defined are handled in some way that doesn't break the build. + 'actions': [ + { + 'action_name': 'Action copy braces ${PRODUCT_NAME} ${FOO}', + 'description': 'Action copy braces ${PRODUCT_NAME} ${FOO}', + 'inputs': [ '${SOURCE_ROOT}/main.c' ], + # Referencing ${PRODUCT_NAME} in action outputs doesn't work with + # the Xcode generator (PRODUCT_NAME expands to "Test Support"). + 'outputs': [ '<(PRODUCT_DIR)/action-copy-brace.txt' ], + 'action': [ 'cp', '${SOURCE_ROOT}/main.c', + '<(PRODUCT_DIR)/action-copy-brace.txt' ], + }, + { + 'action_name': 'Action copy parens $(PRODUCT_NAME) $(FOO)', + 'description': 'Action copy parens $(PRODUCT_NAME) $(FOO)', + 'inputs': [ '$(SOURCE_ROOT)/main.c' ], + # Referencing $(PRODUCT_NAME) in action outputs doesn't work with + # the Xcode generator (PRODUCT_NAME expands to "Test Support"). + 'outputs': [ '<(PRODUCT_DIR)/action-copy-paren.txt' ], + 'action': [ 'cp', '$(SOURCE_ROOT)/main.c', + '<(PRODUCT_DIR)/action-copy-paren.txt' ], + }, + { + 'action_name': 'Action copy bare $PRODUCT_NAME $FOO', + 'description': 'Action copy bare $PRODUCT_NAME $FOO', + 'inputs': [ '$SOURCE_ROOT/main.c' ], + # Referencing $PRODUCT_NAME in action outputs doesn't work with + # the Xcode generator (PRODUCT_NAME expands to "Test Support"). + 'outputs': [ '<(PRODUCT_DIR)/action-copy-bare.txt' ], + 'action': [ 'cp', '$SOURCE_ROOT/main.c', + '<(PRODUCT_DIR)/action-copy-bare.txt' ], + }, + ], + # Env vars in xcode_settings. + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + 'STRING_KEY': '/Source/Project', + + 'BRACE_DEPENDENT_KEY2': '${STRING_KEY}/${PRODUCT_NAME}', + 'BRACE_DEPENDENT_KEY1': 'D:${BRACE_DEPENDENT_KEY2}', + 'BRACE_DEPENDENT_KEY3': '${PRODUCT_TYPE}:${BRACE_DEPENDENT_KEY1}', + + 'PAREN_DEPENDENT_KEY2': '$(STRING_KEY)/$(PRODUCT_NAME)', + 'PAREN_DEPENDENT_KEY1': 'D:$(PAREN_DEPENDENT_KEY2)', + 'PAREN_DEPENDENT_KEY3': '$(PRODUCT_TYPE):$(PAREN_DEPENDENT_KEY1)', + + 'BARE_DEPENDENT_KEY2': '$STRING_KEY/$PRODUCT_NAME', + 'BARE_DEPENDENT_KEY1': 'D:$BARE_DEPENDENT_KEY2', + 'BARE_DEPENDENT_KEY3': '$PRODUCT_TYPE:$BARE_DEPENDENT_KEY1', + + 'MIXED_DEPENDENT_KEY': '${STRING_KEY}:$(PRODUCT_NAME):$MACH_O_TYPE', + }, + # Env vars in rules. The $FOO's are here to test that env vars that + # aren't defined are handled in some way that doesn't break the build. + 'rules': [ + { + 'rule_name': 'brace_rule', + 'message': 'Rule braces ${PRODUCT_NAME} ${FOO} <(RULE_INPUT_NAME)', + 'extension': 'ext1', + 'inputs': [ '${SOURCE_ROOT}/main.c' ], + 'outputs': [ '<(PRODUCT_DIR)/rule-copy-brace.txt' ], + 'action': [ 'cp', '${SOURCE_ROOT}/main.c', + '<(PRODUCT_DIR)/rule-copy-brace.txt' ], + }, + { + 'rule_name': 'paren_rule', + 'message': 'Rule parens $(PRODUCT_NAME) $(FOO) <(RULE_INPUT_NAME)', + 'extension': 'ext2', + 'inputs': [ '$(SOURCE_ROOT)/main.c' ], + 'outputs': [ '<(PRODUCT_DIR)/rule-copy-paren.txt' ], + 'action': [ 'cp', '$(SOURCE_ROOT)/main.c', + '<(PRODUCT_DIR)/rule-copy-paren.txt' ], + }, + # TODO: Fails in xcode. Looks like a bug in the xcode generator though + # (which uses makefiles for rules, and thinks $PRODUCT_NAME is + # $(P)RODUCT_NAME). + #{ + # 'rule_name': 'bare_rule', + # 'message': 'Rule copy bare $PRODUCT_NAME $FOO', + # 'extension': 'ext3', + # 'inputs': [ '$SOURCE_ROOT/main.c' ], + # 'outputs': [ '<(PRODUCT_DIR)/rule-copy-bare.txt' ], + # 'action': [ 'cp', '$SOURCE_ROOT/main.c', + # '<(PRODUCT_DIR)/rule-copy-bare.txt' ], + #}, + ], + }, + ], +} diff --git a/tools/gyp/test/mac/xcode-gcc/aliasing.cc b/tools/gyp/test/mac/xcode-gcc/aliasing.cc new file mode 100644 index 00000000000000..16a41efb15cc33 --- /dev/null +++ b/tools/gyp/test/mac/xcode-gcc/aliasing.cc @@ -0,0 +1,13 @@ +#include + +void check(int* h, long* k) { + *h = 1; + *k = 0; + printf("%d\n", *h); +} + +int main(void) { + long k; + check((int*)&k, &k); + return 0; +} diff --git a/tools/gyp/test/mac/xcode-gcc/test-clang.gyp b/tools/gyp/test/mac/xcode-gcc/test-clang.gyp new file mode 100644 index 00000000000000..9f4a98ae73fce4 --- /dev/null +++ b/tools/gyp/test/mac/xcode-gcc/test-clang.gyp @@ -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. +{ + 'make_global_settings': [ + ['CC', '/usr/bin/clang'], + ['CXX', '/usr/bin/clang++'], + ], + + 'targets': [ + { + 'target_name': 'aliasing_yes', + 'type': 'executable', + 'sources': [ 'aliasing.cc', ], + 'xcode_settings': { + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + 'GCC_STRICT_ALIASING': 'YES', + 'GCC_OPTIMIZATION_LEVEL': 2, + }, + }, + { + 'target_name': 'aliasing_no', + 'type': 'executable', + 'sources': [ 'aliasing.cc', ], + 'xcode_settings': { + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + 'GCC_STRICT_ALIASING': 'NO', + 'GCC_OPTIMIZATION_LEVEL': 2, + }, + }, + { + 'target_name': 'aliasing_default', + 'type': 'executable', + 'sources': [ 'aliasing.cc', ], + 'xcode_settings': { + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + 'GCC_OPTIMIZATION_LEVEL': 2, + }, + }, + ], +} + diff --git a/tools/gyp/test/mac/xcode-gcc/test.gyp b/tools/gyp/test/mac/xcode-gcc/test.gyp new file mode 100644 index 00000000000000..1ca8b215d8763f --- /dev/null +++ b/tools/gyp/test/mac/xcode-gcc/test.gyp @@ -0,0 +1,60 @@ +# 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. +{ + 'target_defaults': { + 'xcode_settings': { + 'GCC_TREAT_WARNINGS_AS_ERRORS': 'YES', + }, + }, + + 'variables': { + # Non-failing tests should check that these trivial files in every language + # still compile correctly. + 'valid_sources': [ + 'valid_c.c', + 'valid_cc.cc', + 'valid_m.m', + 'valid_mm.mm', + ], + }, + + # Targets come in pairs: 'foo' and 'foo-fail', with the former building with + # no warnings and the latter not. + 'targets': [ + # GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO (default: YES): + { + 'target_name': 'warn_about_invalid_offsetof_macro', + 'type': 'executable', + 'sources': [ + 'warn_about_invalid_offsetof_macro.cc', + '<@(valid_sources)', + ], + 'xcode_settings': { + 'GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO': 'NO', + }, + }, + { + 'target_name': 'warn_about_invalid_offsetof_macro-fail', + 'type': 'executable', + 'sources': [ 'warn_about_invalid_offsetof_macro.cc', ], + }, + # GCC_WARN_ABOUT_MISSING_NEWLINE (default: NO): + { + 'target_name': 'warn_about_missing_newline', + 'type': 'executable', + 'sources': [ + 'warn_about_missing_newline.c', + '<@(valid_sources)', + ], + }, + { + 'target_name': 'warn_about_missing_newline-fail', + 'type': 'executable', + 'sources': [ 'warn_about_missing_newline.c', ], + 'xcode_settings': { + 'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/xcode-gcc/valid_c.c b/tools/gyp/test/mac/xcode-gcc/valid_c.c new file mode 100644 index 00000000000000..2b10ac3ed75818 --- /dev/null +++ b/tools/gyp/test/mac/xcode-gcc/valid_c.c @@ -0,0 +1,8 @@ +// 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. + +// This file exists to test that valid C files compile correctly. + +void FunctionInCFile(void) { +} diff --git a/tools/gyp/test/mac/xcode-gcc/valid_cc.cc b/tools/gyp/test/mac/xcode-gcc/valid_cc.cc new file mode 100644 index 00000000000000..31cddc3c9cc37d --- /dev/null +++ b/tools/gyp/test/mac/xcode-gcc/valid_cc.cc @@ -0,0 +1,8 @@ +// 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. + +// This file exists to test that valid C++ files compile correctly. + +void FunctionInCCFile() { +} diff --git a/tools/gyp/test/mac/xcode-gcc/valid_m.m b/tools/gyp/test/mac/xcode-gcc/valid_m.m new file mode 100644 index 00000000000000..95bddb27238fd0 --- /dev/null +++ b/tools/gyp/test/mac/xcode-gcc/valid_m.m @@ -0,0 +1,8 @@ +// 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. + +// This file exists to test that valid Objective-C files compile correctly. + +void FunctionInMFile(void) { +} diff --git a/tools/gyp/test/mac/xcode-gcc/valid_mm.mm b/tools/gyp/test/mac/xcode-gcc/valid_mm.mm new file mode 100644 index 00000000000000..a7db7e3ad6de74 --- /dev/null +++ b/tools/gyp/test/mac/xcode-gcc/valid_mm.mm @@ -0,0 +1,8 @@ +// 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. + +// This file exists to test that valid Objective-C++ files compile correctly. + +void FunctionInMMFile() { +} diff --git a/tools/gyp/test/mac/xcode-gcc/warn_about_invalid_offsetof_macro.cc b/tools/gyp/test/mac/xcode-gcc/warn_about_invalid_offsetof_macro.cc new file mode 100644 index 00000000000000..4a4612be0dc9ed --- /dev/null +++ b/tools/gyp/test/mac/xcode-gcc/warn_about_invalid_offsetof_macro.cc @@ -0,0 +1,15 @@ +// 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. + +#define offsetof(st, m) ((unsigned)((char*)&((st*)0)->m - (char*)0)) + +struct MyStruct { + virtual void MyFunc() = 0; + int my_member; +}; + +int main() { + unsigned x = offsetof(MyStruct, my_member); + return x ? 0 : 1; +} diff --git a/tools/gyp/test/mac/xcode-gcc/warn_about_missing_newline.c b/tools/gyp/test/mac/xcode-gcc/warn_about_missing_newline.c new file mode 100644 index 00000000000000..6faf0895dbb686 --- /dev/null +++ b/tools/gyp/test/mac/xcode-gcc/warn_about_missing_newline.c @@ -0,0 +1,8 @@ +// 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. + +// Important: Don't terminate this file with a newline. +int main() { + return 0; +} \ No newline at end of file diff --git a/tools/gyp/test/mac/xcode-support-actions/source.c b/tools/gyp/test/mac/xcode-support-actions/source.c new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/mac/xcode-support-actions/test.gyp b/tools/gyp/test/mac/xcode-support-actions/test.gyp new file mode 100644 index 00000000000000..ad81b8c456c120 --- /dev/null +++ b/tools/gyp/test/mac/xcode-support-actions/test.gyp @@ -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 --git a/tools/gyp/test/mac/xctest/MyClass.h b/tools/gyp/test/mac/xctest/MyClass.h new file mode 100644 index 00000000000000..dde13aa33d75a0 --- /dev/null +++ b/tools/gyp/test/mac/xctest/MyClass.h @@ -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 --git a/tools/gyp/test/mac/xctest/MyClass.m b/tools/gyp/test/mac/xctest/MyClass.m new file mode 100644 index 00000000000000..df11471b075b79 --- /dev/null +++ b/tools/gyp/test/mac/xctest/MyClass.m @@ -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 --git a/tools/gyp/test/mac/xctest/TestCase.m b/tools/gyp/test/mac/xctest/TestCase.m new file mode 100644 index 00000000000000..36846a1fda24b2 --- /dev/null +++ b/tools/gyp/test/mac/xctest/TestCase.m @@ -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 --git a/tools/gyp/test/mac/xctest/resource.txt b/tools/gyp/test/mac/xctest/resource.txt new file mode 100644 index 00000000000000..257cc5642cb1a0 --- /dev/null +++ b/tools/gyp/test/mac/xctest/resource.txt @@ -0,0 +1 @@ +foo diff --git a/tools/gyp/test/mac/xctest/test.gyp b/tools/gyp/test/mac/xctest/test.gyp new file mode 100644 index 00000000000000..ac25656b3561d3 --- /dev/null +++ b/tools/gyp/test/mac/xctest/test.gyp @@ -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 --git a/tools/gyp/test/mac/xcuitest/Info.plist b/tools/gyp/test/mac/xcuitest/Info.plist new file mode 100644 index 00000000000000..ae8852b8360897 --- /dev/null +++ b/tools/gyp/test/mac/xcuitest/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.yourcompany.${PRODUCT_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSPrincipalClass + + + diff --git a/tools/gyp/test/mac/xcuitest/MyAppDelegate.h b/tools/gyp/test/mac/xcuitest/MyAppDelegate.h new file mode 100644 index 00000000000000..445be2cb427e27 --- /dev/null +++ b/tools/gyp/test/mac/xcuitest/MyAppDelegate.h @@ -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 MyAppDelegate : NSObject +@end diff --git a/tools/gyp/test/mac/xcuitest/MyAppDelegate.m b/tools/gyp/test/mac/xcuitest/MyAppDelegate.m new file mode 100644 index 00000000000000..6ad60fa9d4f64f --- /dev/null +++ b/tools/gyp/test/mac/xcuitest/MyAppDelegate.m @@ -0,0 +1,19 @@ +// 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 "MyAppDelegate.h" + + +@implementation MyAppDelegate +@synthesize window; + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + self.window = [[UIWindow alloc] init]; + self.window.rootViewController = [[UIViewController alloc] init]; + [self.window makeKeyAndVisible]; + return YES; +} + +@end diff --git a/tools/gyp/test/mac/xcuitest/TestCase.m b/tools/gyp/test/mac/xcuitest/TestCase.m new file mode 100644 index 00000000000000..1f32b7af745709 --- /dev/null +++ b/tools/gyp/test/mac/xcuitest/TestCase.m @@ -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. + +#import + +@interface TestCase : XCTestCase +@end + +@implementation TestCase +- (void)testFoo { + XCUIApplication *foo = [[XCUIApplication alloc] init]; + XCTAssertNotNil(foo, @"expected non-nil object"); +} +@end diff --git a/tools/gyp/test/mac/xcuitest/main.m b/tools/gyp/test/mac/xcuitest/main.m new file mode 100644 index 00000000000000..e7cb62e6394627 --- /dev/null +++ b/tools/gyp/test/mac/xcuitest/main.m @@ -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. + +#import + +#import "MyAppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + UIApplicationMain(argc, argv, + nil, NSStringFromClass([MyAppDelegate class])); + } + return 1; +} diff --git a/tools/gyp/test/mac/xcuitest/resource.txt b/tools/gyp/test/mac/xcuitest/resource.txt new file mode 100644 index 00000000000000..257cc5642cb1a0 --- /dev/null +++ b/tools/gyp/test/mac/xcuitest/resource.txt @@ -0,0 +1 @@ +foo diff --git a/tools/gyp/test/mac/xcuitest/test.gyp b/tools/gyp/test/mac/xcuitest/test.gyp new file mode 100644 index 00000000000000..80cdf9032d095c --- /dev/null +++ b/tools/gyp/test/mac/xcuitest/test.gyp @@ -0,0 +1,69 @@ +# 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. + +{ + 'target_defaults': { + 'xcode_settings': { + 'SDKROOT': 'iphoneos', + 'FRAMEWORK_SEARCH_PATHS': [ + '$(inherited)', + '$(DEVELOPER_FRAMEWORKS_DIR)', + ], + 'OTHER_LDFLAGS': [ + '$(inherited)', + '-ObjC', + ], + 'GCC_PREFIX_HEADER': '', + 'CLANG_ENABLE_OBJC_ARC': 'YES', + 'INFOPLIST_FILE': 'Info.plist', + }, + }, + 'targets': [ + { + 'target_name': 'testApp', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'MyAppDelegate.h', + 'MyAppDelegate.m', + 'main.m', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + '$(SDKROOT)/System/Library/Frameworks/UIKit.framework', + ], + }, + }, + { + 'target_name': 'tests', + 'type': 'loadable_module', + 'mac_bundle': 1, + 'mac_xcuitest_bundle': 1, + 'sources': [ + 'TestCase.m', + ], + 'dependencies': [ + 'testApp', + ], + 'mac_bundle_resources': [ + 'resource.txt', + ], + 'variables': { + # This must *not* be set for xctest ui tests. + 'xctest_host': '', + }, + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/XCTest.framework', + ] + }, + 'xcode_settings': { + 'WRAPPER_EXTENSION': 'xctest', + 'TEST_TARGET_NAME': 'testApp', + }, + }, + ], +} + diff --git a/tools/gyp/test/make/dependencies.gyp b/tools/gyp/test/make/dependencies.gyp new file mode 100644 index 00000000000000..e2bee24fcefd9f --- /dev/null +++ b/tools/gyp/test/make/dependencies.gyp @@ -0,0 +1,15 @@ +# 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': 'main', + 'type': 'executable', + 'sources': [ + 'main.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/make/gyptest-dependencies.py b/tools/gyp/test/make/gyptest-dependencies.py new file mode 100644 index 00000000000000..d215f767825214 --- /dev/null +++ b/tools/gyp/test/make/gyptest-dependencies.py @@ -0,0 +1,26 @@ +#!/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 .d files and all.deps are properly generated. +""" + +import TestGyp + +# .d files are only used by the make build. +test = TestGyp.TestGyp(formats=['make']) + +test.run_gyp('dependencies.gyp') + +test.build('dependencies.gyp', test.ALL) + +deps_file = test.built_file_path(".deps/out/Default/obj.target/main/main.o.d") +test.must_contain(deps_file, "main.h") + +# Build a second time to make sure we generate all.deps. +test.build('dependencies.gyp', test.ALL) + +test.pass_test() diff --git a/tools/gyp/test/make/gyptest-noload.py b/tools/gyp/test/make/gyptest-noload.py new file mode 100644 index 00000000000000..1f5103315cfcc1 --- /dev/null +++ b/tools/gyp/test/make/gyptest-noload.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +# Copyright (c) 2010 Google 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 the use of the NO_LOAD flag which makes loading sub .mk files +optional. +""" + +# Python 2.5 needs this for the with statement. +from __future__ import with_statement + +import os +import TestGyp + +test = TestGyp.TestGyp(formats=['make']) + +test.run_gyp('all.gyp', chdir='noload') + +test.relocate('noload', 'relocate/noload') + +test.build('build/all.gyp', test.ALL, chdir='relocate/noload') +test.run_built_executable('exe', chdir='relocate/noload', + stdout='Hello from shared.c.\n') + +# Just sanity test that NO_LOAD=lib doesn't break anything. +test.build('build/all.gyp', test.ALL, chdir='relocate/noload', + arguments=['NO_LOAD=lib']) +test.run_built_executable('exe', chdir='relocate/noload', + stdout='Hello from shared.c.\n') +test.build('build/all.gyp', test.ALL, chdir='relocate/noload', + arguments=['NO_LOAD=z']) +test.run_built_executable('exe', chdir='relocate/noload', + stdout='Hello from shared.c.\n') + +# Make sure we can rebuild without reloading the sub .mk file. +with open('relocate/noload/main.c', 'a') as src_file: + src_file.write("\n") +test.build('build/all.gyp', test.ALL, chdir='relocate/noload', + arguments=['NO_LOAD=lib']) +test.run_built_executable('exe', chdir='relocate/noload', + stdout='Hello from shared.c.\n') + +# Change shared.c, but verify that it doesn't get rebuild if we don't load it. +with open('relocate/noload/lib/shared.c', 'w') as shared_file: + shared_file.write( + '#include "shared.h"\n' + 'const char kSharedStr[] = "modified";\n' + ) +test.build('build/all.gyp', test.ALL, chdir='relocate/noload', + arguments=['NO_LOAD=lib']) +test.run_built_executable('exe', chdir='relocate/noload', + stdout='Hello from shared.c.\n') + +test.pass_test() diff --git a/tools/gyp/test/make/main.cc b/tools/gyp/test/make/main.cc new file mode 100644 index 00000000000000..3b9a705c243444 --- /dev/null +++ b/tools/gyp/test/make/main.cc @@ -0,0 +1,12 @@ +/* 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. */ + +#include + +#include "main.h" + +int main(void) { + printf("hello world\n"); + return 0; +} diff --git a/tools/gyp/test/make/main.h b/tools/gyp/test/make/main.h new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/make/noload/all.gyp b/tools/gyp/test/make/noload/all.gyp new file mode 100644 index 00000000000000..1617a9e97c9492 --- /dev/null +++ b/tools/gyp/test/make/noload/all.gyp @@ -0,0 +1,18 @@ +# Copyright (c) 2010 Google 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', + 'sources': [ + 'main.c', + ], + 'dependencies': [ + 'lib/shared.gyp:shared', + ], + }, + ], +} diff --git a/tools/gyp/test/make/noload/lib/shared.c b/tools/gyp/test/make/noload/lib/shared.c new file mode 100644 index 00000000000000..51776c5acfab6d --- /dev/null +++ b/tools/gyp/test/make/noload/lib/shared.c @@ -0,0 +1,3 @@ +#include "shared.h" + +const char kSharedStr[] = "shared.c"; diff --git a/tools/gyp/test/make/noload/lib/shared.gyp b/tools/gyp/test/make/noload/lib/shared.gyp new file mode 100644 index 00000000000000..8a8841b3a06e82 --- /dev/null +++ b/tools/gyp/test/make/noload/lib/shared.gyp @@ -0,0 +1,16 @@ +# 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': 'shared', + 'type': 'shared_library', + 'sources': [ + 'shared.c', + 'shared.h', + ], + }, + ], +} diff --git a/tools/gyp/test/make/noload/lib/shared.h b/tools/gyp/test/make/noload/lib/shared.h new file mode 100644 index 00000000000000..a21da7538bf08b --- /dev/null +++ b/tools/gyp/test/make/noload/lib/shared.h @@ -0,0 +1 @@ +extern const char kSharedStr[]; diff --git a/tools/gyp/test/make/noload/main.c b/tools/gyp/test/make/noload/main.c new file mode 100644 index 00000000000000..26ec1889ad3501 --- /dev/null +++ b/tools/gyp/test/make/noload/main.c @@ -0,0 +1,9 @@ +#include + +#include "lib/shared.h" + +int main(void) +{ + printf("Hello from %s.\n", kSharedStr); + return 0; +} diff --git a/tools/gyp/test/make_global_settings/ar/gyptest-make_global_settings_ar.py b/tools/gyp/test/make_global_settings/ar/gyptest-make_global_settings_ar.py new file mode 100644 index 00000000000000..1c0f889c03fca5 --- /dev/null +++ b/tools/gyp/test/make_global_settings/ar/gyptest-make_global_settings_ar.py @@ -0,0 +1,106 @@ +#!/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 verify_ar(tst, ars=None, rel_path=False, is_cross=True): + ars = ars or {} + rel_path = rel_path or set() + for toolset in ['host', 'target']: + ar = ars.get(toolset) + ar_expected = fix_ar(ar, toolset in rel_path, tst) + ar_suffix = '' if toolset == 'target' else 'host' + if toolset == 'host': + ar_expected = ar_expected or ('lib.exe' if sys.platform == 'win32' else 'ar') + if tst.is_make: + ar_suffix = ar_suffix and '.' + ar_suffix + filename = 'Makefile' + if toolset == 'target' and ar is None: + tst.must_not_contain(filename, 'AR ?= ') + return + ar_rule = 'AR%s ?= %s' % (ar_suffix, ar_expected) + elif tst.is_ninja: + if not is_cross and toolset == 'host': + return + filename = 'out/Default/build.ninja' + ar_suffix = ar_suffix and '_' + ar_suffix + ar_expected = ar_expected or ('lib.exe' if sys.platform == 'win32' else 'ar') + ar_rule = 'ar%s = %s' % (ar_suffix, ar_expected) + else: + tst.fail_test() + return + + tst.must_contain(filename, ar_rule) + + +def fix_ar(ar, rel_path, tst): + if rel_path: + if ar is None: + ar_expected = '' + elif tst.is_make: + ar_expected = '$(abspath %s)' % ar + elif tst.is_ninja: + ar_expected = os.path.join('..', '..', ar) + else: + tst.fail_test() + return + else: + ar_expected = ar or '' + return ar_expected + + +test_format = ['ninja'] +if sys.platform.startswith('linux') or sys.platform == 'darwin': + test_format += ['make'] + +test = TestGyp.TestGyp(formats=test_format) + +# Check default values +test.run_gyp('make_global_settings_ar.gyp') +verify_ar(test, is_cross=False) + + +# Check default values with GYP_CROSSCOMPILE enabled. +with TestGyp.LocalEnv({'GYP_CROSSCOMPILE': '1'}): + test.run_gyp('make_global_settings_ar.gyp') +verify_ar(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(test, ars={'target': 'my_ar'}, rel_path={'target', 'host'}) + + +# 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(test, ars={'target': 'my_ar_target1', 'host': 'my_ar_host1'}, rel_path={'target', 'host'}) + + +# 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. +ar_target_expected = None +if test.is_ninja: + ar_target_expected = 'lib.exe' if sys.platform == 'win32' else 'my_ar_target2' +verify_ar(test, ars={'target': ar_target_expected, 'host': 'my_ar_host2'}) + + +# 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(test, ars={'target': 'my_ar_target3', 'host': 'my_ar_host3'}, rel_path={'target'}) + + +test.pass_test() diff --git a/tools/gyp/test/make_global_settings/ar/make_global_settings_ar.gyp b/tools/gyp/test/make_global_settings/ar/make_global_settings_ar.gyp new file mode 100644 index 00000000000000..3430d82a517aec --- /dev/null +++ b/tools/gyp/test/make_global_settings/ar/make_global_settings_ar.gyp @@ -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 --git a/tools/gyp/test/make_global_settings/basics/gyptest-make_global_settings.py b/tools/gyp/test/make_global_settings/basics/gyptest-make_global_settings.py new file mode 100644 index 00000000000000..8f48875967d3de --- /dev/null +++ b/tools/gyp/test/make_global_settings/basics/gyptest-make_global_settings.py @@ -0,0 +1,51 @@ +#!/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 make_global_settings. +""" + +from __future__ import print_function + +import os +import sys +import TestGyp + +print("This test is currently disabled: https://crbug.com/483696.") +sys.exit(0) + +test_format = ['ninja'] +if sys.platform.startswith('linux') or sys.platform == 'darwin': + test_format += ['make'] + +test = TestGyp.TestGyp(formats=test_format) + +test.run_gyp('make_global_settings.gyp') + +if test.format == 'make': + cc_expected = """ifneq (,$(filter $(origin CC), undefined default)) + CC = $(abspath clang) +endif +""" + if sys.platform.startswith('linux'): + link_expected = """ +LINK ?= $(abspath clang) +""" + elif sys.platform == 'darwin': + link_expected = """ +LINK ?= $(abspath clang) +""" + test.must_contain('Makefile', cc_expected) + test.must_contain('Makefile', link_expected) +if test.format == 'ninja': + cc_expected = 'cc = ' + os.path.join('..', '..', 'clang') + ld_expected = 'ld = $cc' + if sys.platform == 'win32': + ld_expected = 'link.exe' + test.must_contain('out/Default/build.ninja', cc_expected) + test.must_contain('out/Default/build.ninja', ld_expected) + +test.pass_test() diff --git a/tools/gyp/test/make_global_settings/basics/make_global_settings.gyp b/tools/gyp/test/make_global_settings/basics/make_global_settings.gyp new file mode 100644 index 00000000000000..47dbc8570fe7dc --- /dev/null +++ b/tools/gyp/test/make_global_settings/basics/make_global_settings.gyp @@ -0,0 +1,17 @@ +# 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', 'clang'], + ['LINK', 'clang'], + ], + 'targets': [ + { + 'target_name': 'test', + 'type': 'static_library', + 'sources': [ 'foo.c' ], + }, + ], +} diff --git a/tools/gyp/test/make_global_settings/env-wrapper/gyptest-wrapper.py b/tools/gyp/test/make_global_settings/env-wrapper/gyptest-wrapper.py new file mode 100644 index 00000000000000..409799e315a1ec --- /dev/null +++ b/tools/gyp/test/make_global_settings/env-wrapper/gyptest-wrapper.py @@ -0,0 +1,51 @@ +#!/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 *_wrapper in environment. +""" + +from __future__ import print_function + +import os +import sys +import TestGyp + +print("This test is currently disabled: https://crbug.com/483696.") +sys.exit(0) + +test_format = ['ninja'] + +os.environ['CC_wrapper'] = 'distcc' +os.environ['LINK_wrapper'] = 'distlink' +os.environ['CC.host_wrapper'] = 'ccache' + +test = TestGyp.TestGyp(formats=test_format) + +old_env = dict(os.environ) +os.environ['GYP_CROSSCOMPILE'] = '1' +test.run_gyp('wrapper.gyp') +os.environ.clear() +os.environ.update(old_env) + +if test.format == 'ninja': + cc_expected = ('cc = ' + os.path.join('..', '..', 'distcc') + ' ' + + os.path.join('..', '..', 'clang')) + cc_host_expected = ('cc_host = ' + os.path.join('..', '..', 'ccache') + ' ' + + os.path.join('..', '..', 'clang')) + ld_expected = 'ld = ../../distlink $cc' + if sys.platform != 'win32': + ldxx_expected = 'ldxx = ../../distlink $cxx' + + if sys.platform == 'win32': + ld_expected = 'link.exe' + test.must_contain('out/Default/build.ninja', cc_expected) + test.must_contain('out/Default/build.ninja', cc_host_expected) + test.must_contain('out/Default/build.ninja', ld_expected) + if sys.platform != 'win32': + test.must_contain('out/Default/build.ninja', ldxx_expected) + +test.pass_test() diff --git a/tools/gyp/test/make_global_settings/env-wrapper/wrapper.gyp b/tools/gyp/test/make_global_settings/env-wrapper/wrapper.gyp new file mode 100644 index 00000000000000..1698d71dd4a0c9 --- /dev/null +++ b/tools/gyp/test/make_global_settings/env-wrapper/wrapper.gyp @@ -0,0 +1,17 @@ +# 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', 'clang'], + ['CC.host', 'clang'], + ], + 'targets': [ + { + 'target_name': 'test', + 'type': 'static_library', + 'sources': [ 'foo.c' ], + }, + ], +} diff --git a/tools/gyp/test/make_global_settings/full-toolchain/bar.cc b/tools/gyp/test/make_global_settings/full-toolchain/bar.cc new file mode 100644 index 00000000000000..afb422ba1a8654 --- /dev/null +++ b/tools/gyp/test/make_global_settings/full-toolchain/bar.cc @@ -0,0 +1 @@ +#error Not a real source file diff --git a/tools/gyp/test/make_global_settings/full-toolchain/foo.c b/tools/gyp/test/make_global_settings/full-toolchain/foo.c new file mode 100644 index 00000000000000..afb422ba1a8654 --- /dev/null +++ b/tools/gyp/test/make_global_settings/full-toolchain/foo.c @@ -0,0 +1 @@ +#error Not a real source file diff --git a/tools/gyp/test/make_global_settings/full-toolchain/gyptest-make_global_settings.py b/tools/gyp/test/make_global_settings/full-toolchain/gyptest-make_global_settings.py new file mode 100644 index 00000000000000..542fd631c24938 --- /dev/null +++ b/tools/gyp/test/make_global_settings/full-toolchain/gyptest-make_global_settings.py @@ -0,0 +1,53 @@ +#!/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. +""" + +from __future__ import print_function + +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) + +print("This test is currently disabled: https://crbug.com/483696.") +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 --git a/tools/gyp/test/make_global_settings/full-toolchain/make_global_settings.gyp b/tools/gyp/test/make_global_settings/full-toolchain/make_global_settings.gyp new file mode 100644 index 00000000000000..2c3266322d4f76 --- /dev/null +++ b/tools/gyp/test/make_global_settings/full-toolchain/make_global_settings.gyp @@ -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 --git a/tools/gyp/test/make_global_settings/full-toolchain/my_nm.py b/tools/gyp/test/make_global_settings/full-toolchain/my_nm.py new file mode 100644 index 00000000000000..2c4e678110bb21 --- /dev/null +++ b/tools/gyp/test/make_global_settings/full-toolchain/my_nm.py @@ -0,0 +1,9 @@ +#!/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. +from __future__ import print_function +import sys +print(sys.argv) +with open('RAN_MY_NM', 'w') as f: + f.write('RAN_MY_NM') diff --git a/tools/gyp/test/make_global_settings/full-toolchain/my_readelf.py b/tools/gyp/test/make_global_settings/full-toolchain/my_readelf.py new file mode 100644 index 00000000000000..626665435e680e --- /dev/null +++ b/tools/gyp/test/make_global_settings/full-toolchain/my_readelf.py @@ -0,0 +1,9 @@ +#!/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. +from __future__ import print_function +import sys +print(sys.argv) +with open('RAN_MY_READELF', 'w') as f: + f.write('RAN_MY_READELF') diff --git a/tools/gyp/test/make_global_settings/ld/gyptest-make_global_settings_ld.py b/tools/gyp/test/make_global_settings/ld/gyptest-make_global_settings_ld.py new file mode 100644 index 00000000000000..6ecc962951e6f3 --- /dev/null +++ b/tools/gyp/test/make_global_settings/ld/gyptest-make_global_settings_ld.py @@ -0,0 +1,101 @@ +#!/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 verify_ld(tst, ld=None, rel_path=False, is_target=False): + if rel_path: + if ld is None: + ld_expected = None + elif tst.is_make: + ld_expected = '$(abspath %s)' % ld + elif tst.is_ninja: + ld_expected = os.path.join('..', '..', ld) + else: + tst.fail_test() + return + else: + ld_expected = ld + + ld_make_suffix = '' + ld_ninja_suffix = '' + if not is_target: + ld_make_suffix = '.host' + ld_ninja_suffix = '_host' + + if tst.is_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. + if ld_expected is None: + tst.must_not_contain('Makefile', 'LD%s ?= ' % ld_make_suffix) + else: + tst.must_contain('Makefile', 'LD%s ?= %s' % (ld_make_suffix, ld_expected)) + elif tst.is_ninja: + if sys.platform == 'win32': + ld_expected = ld_expected or ('link.exe' if is_target else '$ld') + else: + ld_expected = ld_expected or '$cc%s' % ld_ninja_suffix + tst.must_contain('out/Default/build.ninja', 'ld%s = %s' % (ld_ninja_suffix, ld_expected)) + else: + tst.fail_test() + + +test_format = ['ninja'] +if sys.platform.startswith('linux') or sys.platform == 'darwin': + test_format += ['make'] + +test = TestGyp.TestGyp(formats=test_format) + +# Check default values +test.run_gyp('make_global_settings_ld.gyp') +verify_ld(test, is_target=True) + + +# Check default values with GYP_CROSSCOMPILE enabled. +with TestGyp.LocalEnv({'GYP_CROSSCOMPILE': '1'}): + test.run_gyp('make_global_settings_ld.gyp') +verify_ld(test, is_target=True) +verify_ld(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(test, ld='my_ld', rel_path=True, is_target=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(test, ld='my_ld_target1', rel_path=True, is_target=True) +verify_ld(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.is_make: + test.must_not_contain('Makefile', 'my_ld_target2') + test.must_not_contain('Makefile', 'my_ld_host2') +elif test.is_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 --git a/tools/gyp/test/make_global_settings/ld/make_global_settings_ld.gyp b/tools/gyp/test/make_global_settings/ld/make_global_settings_ld.gyp new file mode 100644 index 00000000000000..6837c77326153c --- /dev/null +++ b/tools/gyp/test/make_global_settings/ld/make_global_settings_ld.gyp @@ -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 --git a/tools/gyp/test/make_global_settings/wrapper/gyptest-wrapper.py b/tools/gyp/test/make_global_settings/wrapper/gyptest-wrapper.py new file mode 100644 index 00000000000000..7ef4314b3e8ca1 --- /dev/null +++ b/tools/gyp/test/make_global_settings/wrapper/gyptest-wrapper.py @@ -0,0 +1,52 @@ +#!/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 *_wrapper in make_global_settings. +""" + +from __future__ import print_function + +import os +import sys +import TestGyp + +print("This test is currently disabled: https://crbug.com/483696.") +sys.exit(0) + +test_format = ['ninja'] +if sys.platform.startswith('linux') or sys.platform == 'darwin': + test_format += ['make'] + +test = TestGyp.TestGyp(formats=test_format) + +old_env = dict(os.environ) +os.environ['GYP_CROSSCOMPILE'] = '1' +test.run_gyp('wrapper.gyp') +os.environ.clear() +os.environ.update(old_env) + +if test.format == 'make': + cc_expected = """ifneq (,$(filter $(origin CC), undefined default)) + CC = $(abspath distcc) $(abspath clang) +endif +""" + link_expected = 'LINK ?= $(abspath distlink) $(abspath clang++)' + test.must_contain('Makefile', cc_expected) + test.must_contain('Makefile', link_expected) +if test.format == 'ninja': + cc_expected = ('cc = ' + os.path.join('..', '..', 'distcc') + ' ' + + os.path.join('..', '..', 'clang')) + cc_host_expected = ('cc_host = ' + os.path.join('..', '..', 'ccache') + ' ' + + os.path.join('..', '..', 'clang')) + ld_expected = 'ld = ../../distlink $cc' + if sys.platform == 'win32': + ld_expected = 'link.exe' + test.must_contain('out/Default/build.ninja', cc_expected) + test.must_contain('out/Default/build.ninja', cc_host_expected) + test.must_contain('out/Default/build.ninja', ld_expected) + +test.pass_test() diff --git a/tools/gyp/test/make_global_settings/wrapper/wrapper.gyp b/tools/gyp/test/make_global_settings/wrapper/wrapper.gyp new file mode 100644 index 00000000000000..3d4cd04b164532 --- /dev/null +++ b/tools/gyp/test/make_global_settings/wrapper/wrapper.gyp @@ -0,0 +1,21 @@ +# 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', 'clang'], + ['CC_wrapper', 'distcc'], + ['LINK', 'clang++'], + ['LINK_wrapper', 'distlink'], + ['CC.host', 'clang'], + ['CC.host_wrapper', 'ccache'], + ], + 'targets': [ + { + 'target_name': 'test', + 'type': 'static_library', + 'sources': [ 'foo.c' ], + }, + ], +} diff --git a/tools/gyp/test/many-actions/file0 b/tools/gyp/test/many-actions/file0 new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/many-actions/file1 b/tools/gyp/test/many-actions/file1 new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/many-actions/file2 b/tools/gyp/test/many-actions/file2 new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/many-actions/file3 b/tools/gyp/test/many-actions/file3 new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/many-actions/file4 b/tools/gyp/test/many-actions/file4 new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/many-actions/gyptest-many-actions-unsorted.py b/tools/gyp/test/many-actions/gyptest-many-actions-unsorted.py new file mode 100644 index 00000000000000..6927d1c7a750c3 --- /dev/null +++ b/tools/gyp/test/many-actions/gyptest-many-actions-unsorted.py @@ -0,0 +1,43 @@ +#!/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. + +""" +Make sure lots of actions in the same target don't cause exceeding command +line length. +""" + +from __future__ import print_function + +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) + +# Make sure the optimized cygwin setup doesn't cause problems for incremental +# builds. +test.touch('file1') +test.build('many-actions-unsorted.gyp', test.ALL) + +test.touch('file0') +test.build('many-actions-unsorted.gyp', test.ALL) + +test.touch('file2') +test.touch('file3') +test.touch('file4') +test.build('many-actions-unsorted.gyp', test.ALL) + +test.pass_test() diff --git a/tools/gyp/test/many-actions/gyptest-many-actions.py b/tools/gyp/test/many-actions/gyptest-many-actions.py new file mode 100644 index 00000000000000..4a525d32d65d42 --- /dev/null +++ b/tools/gyp/test/many-actions/gyptest-many-actions.py @@ -0,0 +1,29 @@ +#!/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. + +""" +Make sure lots of actions in the same target don't cause exceeding command +line length. +""" + +from __future__ import print_function + +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.gyp') +test.build('many-actions.gyp', test.ALL) +for i in range(200): + test.built_file_must_exist('generated_%d.h' % i) +test.pass_test() diff --git a/tools/gyp/test/many-actions/many-actions-unsorted.gyp b/tools/gyp/test/many-actions/many-actions-unsorted.gyp new file mode 100644 index 00000000000000..eec79fe8d8570c --- /dev/null +++ b/tools/gyp/test/many-actions/many-actions-unsorted.gyp @@ -0,0 +1,154 @@ +# 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. + +{ + 'target_defaults': { + 'msvs_cygwin_dirs': ['../../../../<(DEPTH)/third_party/cygwin'], + }, + 'targets': [ + { + 'target_name': 'a', + 'type': 'none', + 'actions': [ + # Notice that the inputs go 0, 1, ..., 0, 1, .... This is to test + # a regression in the msvs generator in _AddActions. + { + 'action_name': 'do_0', + 'inputs': ['file0'], + 'outputs': ['<(PRODUCT_DIR)/generated_0.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_0.h', + ], + }, + { + 'action_name': 'do_1', + 'inputs': ['file1'], + 'outputs': ['<(PRODUCT_DIR)/generated_1.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_1.h', + ], + }, + { + 'action_name': 'do_2', + 'inputs': ['file2'], + 'outputs': ['<(PRODUCT_DIR)/generated_2.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_2.h', + ], + }, + { + 'action_name': 'do_3', + 'inputs': ['file3'], + 'outputs': ['<(PRODUCT_DIR)/generated_3.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_3.h', + ], + }, + { + 'action_name': 'do_4', + 'inputs': ['file4'], + 'outputs': ['<(PRODUCT_DIR)/generated_4.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_4.h', + ], + }, + { + 'action_name': 'do_5', + 'inputs': ['file0'], + 'outputs': ['<(PRODUCT_DIR)/generated_5.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_5.h', + ], + }, + { + 'action_name': 'do_6', + 'inputs': ['file1'], + 'outputs': ['<(PRODUCT_DIR)/generated_6.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_6.h', + ], + }, + { + 'action_name': 'do_7', + 'inputs': ['file2'], + 'outputs': ['<(PRODUCT_DIR)/generated_7.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_7.h', + ], + }, + { + 'action_name': 'do_8', + 'inputs': ['file3'], + 'outputs': ['<(PRODUCT_DIR)/generated_8.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_8.h', + ], + }, + { + 'action_name': 'do_9', + 'inputs': ['file4'], + 'outputs': ['<(PRODUCT_DIR)/generated_9.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_9.h', + ], + }, + { + 'action_name': 'do_10', + 'inputs': ['file0'], + 'outputs': ['<(PRODUCT_DIR)/generated_10.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_10.h', + ], + }, + { + 'action_name': 'do_11', + 'inputs': ['file1'], + 'outputs': ['<(PRODUCT_DIR)/generated_11.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_11.h', + ], + }, + { + 'action_name': 'do_12', + 'inputs': ['file2'], + 'outputs': ['<(PRODUCT_DIR)/generated_12.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_12.h', + ], + }, + { + 'action_name': 'do_13', + 'inputs': ['file3'], + 'outputs': ['<(PRODUCT_DIR)/generated_13.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_13.h', + ], + }, + { + 'action_name': 'do_14', + 'inputs': ['file4'], + 'outputs': ['<(PRODUCT_DIR)/generated_14.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_14.h', + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/many-actions/many-actions.gyp b/tools/gyp/test/many-actions/many-actions.gyp new file mode 100644 index 00000000000000..38545d2d88565a --- /dev/null +++ b/tools/gyp/test/many-actions/many-actions.gyp @@ -0,0 +1,1817 @@ +# 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. + +{ + 'target_defaults': { + 'msvs_cygwin_dirs': ['../../../../<(DEPTH)/third_party/cygwin'], + }, + 'targets': [ + { + 'target_name': 'a', + 'type': 'none', + 'actions': [ + { + 'action_name': 'do_0', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_0.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_0.h', + ], + }, + { + 'action_name': 'do_1', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_1.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_1.h', + ], + }, + { + 'action_name': 'do_2', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_2.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_2.h', + ], + }, + { + 'action_name': 'do_3', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_3.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_3.h', + ], + }, + { + 'action_name': 'do_4', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_4.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_4.h', + ], + }, + { + 'action_name': 'do_5', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_5.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_5.h', + ], + }, + { + 'action_name': 'do_6', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_6.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_6.h', + ], + }, + { + 'action_name': 'do_7', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_7.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_7.h', + ], + }, + { + 'action_name': 'do_8', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_8.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_8.h', + ], + }, + { + 'action_name': 'do_9', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_9.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_9.h', + ], + }, + { + 'action_name': 'do_10', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_10.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_10.h', + ], + }, + { + 'action_name': 'do_11', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_11.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_11.h', + ], + }, + { + 'action_name': 'do_12', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_12.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_12.h', + ], + }, + { + 'action_name': 'do_13', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_13.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_13.h', + ], + }, + { + 'action_name': 'do_14', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_14.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_14.h', + ], + }, + { + 'action_name': 'do_15', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_15.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_15.h', + ], + }, + { + 'action_name': 'do_16', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_16.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_16.h', + ], + }, + { + 'action_name': 'do_17', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_17.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_17.h', + ], + }, + { + 'action_name': 'do_18', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_18.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_18.h', + ], + }, + { + 'action_name': 'do_19', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_19.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_19.h', + ], + }, + { + 'action_name': 'do_20', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_20.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_20.h', + ], + }, + { + 'action_name': 'do_21', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_21.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_21.h', + ], + }, + { + 'action_name': 'do_22', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_22.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_22.h', + ], + }, + { + 'action_name': 'do_23', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_23.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_23.h', + ], + }, + { + 'action_name': 'do_24', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_24.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_24.h', + ], + }, + { + 'action_name': 'do_25', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_25.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_25.h', + ], + }, + { + 'action_name': 'do_26', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_26.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_26.h', + ], + }, + { + 'action_name': 'do_27', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_27.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_27.h', + ], + }, + { + 'action_name': 'do_28', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_28.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_28.h', + ], + }, + { + 'action_name': 'do_29', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_29.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_29.h', + ], + }, + { + 'action_name': 'do_30', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_30.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_30.h', + ], + }, + { + 'action_name': 'do_31', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_31.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_31.h', + ], + }, + { + 'action_name': 'do_32', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_32.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_32.h', + ], + }, + { + 'action_name': 'do_33', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_33.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_33.h', + ], + }, + { + 'action_name': 'do_34', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_34.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_34.h', + ], + }, + { + 'action_name': 'do_35', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_35.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_35.h', + ], + }, + { + 'action_name': 'do_36', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_36.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_36.h', + ], + }, + { + 'action_name': 'do_37', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_37.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_37.h', + ], + }, + { + 'action_name': 'do_38', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_38.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_38.h', + ], + }, + { + 'action_name': 'do_39', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_39.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_39.h', + ], + }, + { + 'action_name': 'do_40', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_40.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_40.h', + ], + }, + { + 'action_name': 'do_41', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_41.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_41.h', + ], + }, + { + 'action_name': 'do_42', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_42.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_42.h', + ], + }, + { + 'action_name': 'do_43', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_43.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_43.h', + ], + }, + { + 'action_name': 'do_44', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_44.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_44.h', + ], + }, + { + 'action_name': 'do_45', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_45.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_45.h', + ], + }, + { + 'action_name': 'do_46', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_46.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_46.h', + ], + }, + { + 'action_name': 'do_47', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_47.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_47.h', + ], + }, + { + 'action_name': 'do_48', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_48.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_48.h', + ], + }, + { + 'action_name': 'do_49', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_49.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_49.h', + ], + }, + { + 'action_name': 'do_50', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_50.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_50.h', + ], + }, + { + 'action_name': 'do_51', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_51.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_51.h', + ], + }, + { + 'action_name': 'do_52', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_52.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_52.h', + ], + }, + { + 'action_name': 'do_53', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_53.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_53.h', + ], + }, + { + 'action_name': 'do_54', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_54.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_54.h', + ], + }, + { + 'action_name': 'do_55', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_55.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_55.h', + ], + }, + { + 'action_name': 'do_56', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_56.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_56.h', + ], + }, + { + 'action_name': 'do_57', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_57.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_57.h', + ], + }, + { + 'action_name': 'do_58', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_58.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_58.h', + ], + }, + { + 'action_name': 'do_59', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_59.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_59.h', + ], + }, + { + 'action_name': 'do_60', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_60.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_60.h', + ], + }, + { + 'action_name': 'do_61', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_61.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_61.h', + ], + }, + { + 'action_name': 'do_62', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_62.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_62.h', + ], + }, + { + 'action_name': 'do_63', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_63.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_63.h', + ], + }, + { + 'action_name': 'do_64', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_64.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_64.h', + ], + }, + { + 'action_name': 'do_65', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_65.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_65.h', + ], + }, + { + 'action_name': 'do_66', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_66.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_66.h', + ], + }, + { + 'action_name': 'do_67', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_67.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_67.h', + ], + }, + { + 'action_name': 'do_68', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_68.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_68.h', + ], + }, + { + 'action_name': 'do_69', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_69.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_69.h', + ], + }, + { + 'action_name': 'do_70', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_70.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_70.h', + ], + }, + { + 'action_name': 'do_71', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_71.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_71.h', + ], + }, + { + 'action_name': 'do_72', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_72.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_72.h', + ], + }, + { + 'action_name': 'do_73', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_73.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_73.h', + ], + }, + { + 'action_name': 'do_74', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_74.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_74.h', + ], + }, + { + 'action_name': 'do_75', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_75.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_75.h', + ], + }, + { + 'action_name': 'do_76', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_76.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_76.h', + ], + }, + { + 'action_name': 'do_77', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_77.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_77.h', + ], + }, + { + 'action_name': 'do_78', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_78.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_78.h', + ], + }, + { + 'action_name': 'do_79', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_79.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_79.h', + ], + }, + { + 'action_name': 'do_80', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_80.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_80.h', + ], + }, + { + 'action_name': 'do_81', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_81.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_81.h', + ], + }, + { + 'action_name': 'do_82', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_82.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_82.h', + ], + }, + { + 'action_name': 'do_83', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_83.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_83.h', + ], + }, + { + 'action_name': 'do_84', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_84.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_84.h', + ], + }, + { + 'action_name': 'do_85', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_85.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_85.h', + ], + }, + { + 'action_name': 'do_86', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_86.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_86.h', + ], + }, + { + 'action_name': 'do_87', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_87.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_87.h', + ], + }, + { + 'action_name': 'do_88', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_88.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_88.h', + ], + }, + { + 'action_name': 'do_89', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_89.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_89.h', + ], + }, + { + 'action_name': 'do_90', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_90.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_90.h', + ], + }, + { + 'action_name': 'do_91', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_91.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_91.h', + ], + }, + { + 'action_name': 'do_92', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_92.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_92.h', + ], + }, + { + 'action_name': 'do_93', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_93.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_93.h', + ], + }, + { + 'action_name': 'do_94', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_94.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_94.h', + ], + }, + { + 'action_name': 'do_95', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_95.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_95.h', + ], + }, + { + 'action_name': 'do_96', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_96.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_96.h', + ], + }, + { + 'action_name': 'do_97', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_97.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_97.h', + ], + }, + { + 'action_name': 'do_98', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_98.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_98.h', + ], + }, + { + 'action_name': 'do_99', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_99.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_99.h', + ], + }, + { + 'action_name': 'do_100', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_100.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_100.h', + ], + }, + { + 'action_name': 'do_101', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_101.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_101.h', + ], + }, + { + 'action_name': 'do_102', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_102.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_102.h', + ], + }, + { + 'action_name': 'do_103', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_103.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_103.h', + ], + }, + { + 'action_name': 'do_104', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_104.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_104.h', + ], + }, + { + 'action_name': 'do_105', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_105.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_105.h', + ], + }, + { + 'action_name': 'do_106', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_106.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_106.h', + ], + }, + { + 'action_name': 'do_107', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_107.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_107.h', + ], + }, + { + 'action_name': 'do_108', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_108.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_108.h', + ], + }, + { + 'action_name': 'do_109', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_109.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_109.h', + ], + }, + { + 'action_name': 'do_110', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_110.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_110.h', + ], + }, + { + 'action_name': 'do_111', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_111.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_111.h', + ], + }, + { + 'action_name': 'do_112', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_112.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_112.h', + ], + }, + { + 'action_name': 'do_113', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_113.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_113.h', + ], + }, + { + 'action_name': 'do_114', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_114.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_114.h', + ], + }, + { + 'action_name': 'do_115', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_115.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_115.h', + ], + }, + { + 'action_name': 'do_116', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_116.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_116.h', + ], + }, + { + 'action_name': 'do_117', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_117.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_117.h', + ], + }, + { + 'action_name': 'do_118', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_118.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_118.h', + ], + }, + { + 'action_name': 'do_119', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_119.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_119.h', + ], + }, + { + 'action_name': 'do_120', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_120.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_120.h', + ], + }, + { + 'action_name': 'do_121', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_121.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_121.h', + ], + }, + { + 'action_name': 'do_122', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_122.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_122.h', + ], + }, + { + 'action_name': 'do_123', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_123.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_123.h', + ], + }, + { + 'action_name': 'do_124', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_124.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_124.h', + ], + }, + { + 'action_name': 'do_125', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_125.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_125.h', + ], + }, + { + 'action_name': 'do_126', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_126.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_126.h', + ], + }, + { + 'action_name': 'do_127', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_127.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_127.h', + ], + }, + { + 'action_name': 'do_128', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_128.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_128.h', + ], + }, + { + 'action_name': 'do_129', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_129.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_129.h', + ], + }, + { + 'action_name': 'do_130', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_130.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_130.h', + ], + }, + { + 'action_name': 'do_131', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_131.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_131.h', + ], + }, + { + 'action_name': 'do_132', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_132.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_132.h', + ], + }, + { + 'action_name': 'do_133', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_133.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_133.h', + ], + }, + { + 'action_name': 'do_134', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_134.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_134.h', + ], + }, + { + 'action_name': 'do_135', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_135.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_135.h', + ], + }, + { + 'action_name': 'do_136', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_136.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_136.h', + ], + }, + { + 'action_name': 'do_137', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_137.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_137.h', + ], + }, + { + 'action_name': 'do_138', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_138.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_138.h', + ], + }, + { + 'action_name': 'do_139', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_139.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_139.h', + ], + }, + { + 'action_name': 'do_140', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_140.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_140.h', + ], + }, + { + 'action_name': 'do_141', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_141.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_141.h', + ], + }, + { + 'action_name': 'do_142', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_142.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_142.h', + ], + }, + { + 'action_name': 'do_143', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_143.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_143.h', + ], + }, + { + 'action_name': 'do_144', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_144.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_144.h', + ], + }, + { + 'action_name': 'do_145', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_145.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_145.h', + ], + }, + { + 'action_name': 'do_146', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_146.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_146.h', + ], + }, + { + 'action_name': 'do_147', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_147.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_147.h', + ], + }, + { + 'action_name': 'do_148', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_148.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_148.h', + ], + }, + { + 'action_name': 'do_149', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_149.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_149.h', + ], + }, + { + 'action_name': 'do_150', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_150.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_150.h', + ], + }, + { + 'action_name': 'do_151', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_151.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_151.h', + ], + }, + { + 'action_name': 'do_152', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_152.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_152.h', + ], + }, + { + 'action_name': 'do_153', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_153.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_153.h', + ], + }, + { + 'action_name': 'do_154', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_154.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_154.h', + ], + }, + { + 'action_name': 'do_155', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_155.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_155.h', + ], + }, + { + 'action_name': 'do_156', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_156.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_156.h', + ], + }, + { + 'action_name': 'do_157', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_157.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_157.h', + ], + }, + { + 'action_name': 'do_158', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_158.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_158.h', + ], + }, + { + 'action_name': 'do_159', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_159.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_159.h', + ], + }, + { + 'action_name': 'do_160', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_160.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_160.h', + ], + }, + { + 'action_name': 'do_161', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_161.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_161.h', + ], + }, + { + 'action_name': 'do_162', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_162.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_162.h', + ], + }, + { + 'action_name': 'do_163', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_163.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_163.h', + ], + }, + { + 'action_name': 'do_164', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_164.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_164.h', + ], + }, + { + 'action_name': 'do_165', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_165.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_165.h', + ], + }, + { + 'action_name': 'do_166', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_166.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_166.h', + ], + }, + { + 'action_name': 'do_167', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_167.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_167.h', + ], + }, + { + 'action_name': 'do_168', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_168.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_168.h', + ], + }, + { + 'action_name': 'do_169', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_169.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_169.h', + ], + }, + { + 'action_name': 'do_170', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_170.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_170.h', + ], + }, + { + 'action_name': 'do_171', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_171.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_171.h', + ], + }, + { + 'action_name': 'do_172', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_172.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_172.h', + ], + }, + { + 'action_name': 'do_173', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_173.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_173.h', + ], + }, + { + 'action_name': 'do_174', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_174.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_174.h', + ], + }, + { + 'action_name': 'do_175', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_175.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_175.h', + ], + }, + { + 'action_name': 'do_176', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_176.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_176.h', + ], + }, + { + 'action_name': 'do_177', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_177.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_177.h', + ], + }, + { + 'action_name': 'do_178', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_178.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_178.h', + ], + }, + { + 'action_name': 'do_179', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_179.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_179.h', + ], + }, + { + 'action_name': 'do_180', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_180.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_180.h', + ], + }, + { + 'action_name': 'do_181', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_181.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_181.h', + ], + }, + { + 'action_name': 'do_182', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_182.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_182.h', + ], + }, + { + 'action_name': 'do_183', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_183.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_183.h', + ], + }, + { + 'action_name': 'do_184', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_184.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_184.h', + ], + }, + { + 'action_name': 'do_185', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_185.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_185.h', + ], + }, + { + 'action_name': 'do_186', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_186.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_186.h', + ], + }, + { + 'action_name': 'do_187', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_187.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_187.h', + ], + }, + { + 'action_name': 'do_188', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_188.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_188.h', + ], + }, + { + 'action_name': 'do_189', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_189.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_189.h', + ], + }, + { + 'action_name': 'do_190', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_190.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_190.h', + ], + }, + { + 'action_name': 'do_191', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_191.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_191.h', + ], + }, + { + 'action_name': 'do_192', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_192.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_192.h', + ], + }, + { + 'action_name': 'do_193', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_193.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_193.h', + ], + }, + { + 'action_name': 'do_194', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_194.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_194.h', + ], + }, + { + 'action_name': 'do_195', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_195.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_195.h', + ], + }, + { + 'action_name': 'do_196', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_196.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_196.h', + ], + }, + { + 'action_name': 'do_197', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_197.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_197.h', + ], + }, + { + 'action_name': 'do_198', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_198.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_198.h', + ], + }, + { + 'action_name': 'do_199', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/generated_199.h'], + 'action': [ + 'touch', + '<(PRODUCT_DIR)/generated_199.h', + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/module/gyptest-default.py b/tools/gyp/test/module/gyptest-default.py new file mode 100644 index 00000000000000..7fecf3ca4d2b2a --- /dev/null +++ b/tools/gyp/test/module/gyptest-default.py @@ -0,0 +1,28 @@ +#!/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 simple build of a "Hello, world!" program with loadable modules. The +default for all platforms should be to output the loadable modules to the same +path as the executable. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('module.gyp', chdir='src') + +test.build('module.gyp', test.ALL, chdir='src') + +expect = """\ +Hello from program.c +Hello from lib1.c +Hello from lib2.c +""" +test.run_built_executable('program', chdir='src', stdout=expect) + +test.pass_test() diff --git a/tools/gyp/test/module/src/lib1.c b/tools/gyp/test/module/src/lib1.c new file mode 100644 index 00000000000000..8de0e94bee7050 --- /dev/null +++ b/tools/gyp/test/module/src/lib1.c @@ -0,0 +1,10 @@ +#include + +#ifdef _WIN32 +__declspec(dllexport) +#endif +void module_main(void) +{ + fprintf(stdout, "Hello from lib1.c\n"); + fflush(stdout); +} diff --git a/tools/gyp/test/module/src/lib2.c b/tools/gyp/test/module/src/lib2.c new file mode 100644 index 00000000000000..266396dc91cc3f --- /dev/null +++ b/tools/gyp/test/module/src/lib2.c @@ -0,0 +1,10 @@ +#include + +#ifdef _WIN32 +__declspec(dllexport) +#endif +void module_main(void) +{ + fprintf(stdout, "Hello from lib2.c\n"); + fflush(stdout); +} diff --git a/tools/gyp/test/module/src/module.gyp b/tools/gyp/test/module/src/module.gyp new file mode 100644 index 00000000000000..2bc398bb3bf6b5 --- /dev/null +++ b/tools/gyp/test/module/src/module.gyp @@ -0,0 +1,53 @@ +# 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. + +{ + 'target_defaults': { + 'conditions': [ + ['OS=="win"', { + 'defines': ['PLATFORM_WIN'], + }], + ['OS=="mac" or OS=="ios"', { + 'defines': ['PLATFORM_MAC'], + }], + ['OS=="linux"', { + 'defines': ['PLATFORM_LINUX'], + # Support 64-bit shared libs (also works fine for 32-bit). + 'cflags': ['-fPIC'], + 'libraries': ['-ldl'], + }], + ], + }, + 'targets': [ + { + 'target_name': 'program', + 'type': 'executable', + 'dependencies': [ + 'lib1', + 'lib2', + ], + 'sources': [ + 'program.c', + ], + }, + { + 'target_name': 'lib1', + 'type': 'loadable_module', + 'product_name': 'lib1', + 'product_prefix': '', + 'sources': [ + 'lib1.c', + ], + }, + { + 'target_name': 'lib2', + 'product_name': 'lib2', + 'product_prefix': '', + 'type': 'loadable_module', + 'sources': [ + 'lib2.c', + ], + }, + ], +} diff --git a/tools/gyp/test/module/src/program.c b/tools/gyp/test/module/src/program.c new file mode 100644 index 00000000000000..7cc3dd34663f77 --- /dev/null +++ b/tools/gyp/test/module/src/program.c @@ -0,0 +1,111 @@ +#include +#include + +#if defined(PLATFORM_WIN) +#include +#elif defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) +#include +#include +#include +#include +#define MAX_PATH PATH_MAX +#endif + +#if defined(PLATFORM_WIN) +#define MODULE_SUFFIX ".dll" +#elif defined(PLATFORM_MAC) +#define MODULE_SUFFIX ".so" +#elif defined(PLATFORM_LINUX) +#define MODULE_SUFFIX ".so" +#endif + +typedef void (*module_symbol)(void); +char bin_path[MAX_PATH + 1]; + + +void CallModule(const char* module) { + char module_path[MAX_PATH + 1]; + const char* module_function = "module_main"; + module_symbol funcptr; +#if defined(PLATFORM_WIN) + HMODULE dl; + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + + if (_splitpath_s(bin_path, drive, _MAX_DRIVE, dir, _MAX_DIR, + NULL, 0, NULL, 0)) { + fprintf(stderr, "Failed to split executable path.\n"); + return; + } + if (_makepath_s(module_path, MAX_PATH, drive, dir, module, MODULE_SUFFIX)) { + fprintf(stderr, "Failed to calculate module path.\n"); + return; + } + + dl = LoadLibrary(module_path); + if (!dl) { + fprintf(stderr, "Failed to open module: %s\n", module_path); + return; + } + + funcptr = (module_symbol) GetProcAddress(dl, module_function); + if (!funcptr) { + fprintf(stderr, "Failed to find symbol: %s\n", module_function); + return; + } + funcptr(); + + FreeLibrary(dl); +#elif defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) + void* dl; + char* path_copy = strdup(bin_path); + char* bin_dir = dirname(path_copy); + int path_size = snprintf(module_path, MAX_PATH, "%s/%s%s", bin_dir, module, + MODULE_SUFFIX); + free(path_copy); + if (path_size < 0 || path_size > MAX_PATH) { + fprintf(stderr, "Failed to calculate module path.\n"); + return; + } + module_path[path_size] = 0; + + dl = dlopen(module_path, RTLD_LAZY); + if (!dl) { + fprintf(stderr, "Failed to open module: %s\n", module_path); + return; + } + + funcptr = dlsym(dl, module_function); + if (!funcptr) { + fprintf(stderr, "Failed to find symbol: %s\n", module_function); + return; + } + funcptr(); + + dlclose(dl); +#endif +} + +int main(int argc, char *argv[]) +{ + fprintf(stdout, "Hello from program.c\n"); + fflush(stdout); + +#if defined(PLATFORM_WIN) + if (!GetModuleFileName(NULL, bin_path, MAX_PATH)) { + fprintf(stderr, "Failed to determine executable path.\n"); + return 1; + } +#elif defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) + // Using argv[0] should be OK here since we control how the tests run, and + // can avoid exec and such issues that make it unreliable. + if (!realpath(argv[0], bin_path)) { + fprintf(stderr, "Failed to determine executable path (%s).\n", argv[0]); + return 1; + } +#endif + + CallModule("lib1"); + CallModule("lib2"); + return 0; +} diff --git a/tools/gyp/test/msvs/buildevents/buildevents.gyp b/tools/gyp/test/msvs/buildevents/buildevents.gyp new file mode 100644 index 00000000000000..e0304dd5c61718 --- /dev/null +++ b/tools/gyp/test/msvs/buildevents/buildevents.gyp @@ -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 --git a/tools/gyp/test/msvs/buildevents/gyptest-msbuild-supports-prepostbuild.py b/tools/gyp/test/msvs/buildevents/gyptest-msbuild-supports-prepostbuild.py new file mode 100644 index 00000000000000..208f4345604131 --- /dev/null +++ b/tools/gyp/test/msvs/buildevents/gyptest-msbuild-supports-prepostbuild.py @@ -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 --git a/tools/gyp/test/msvs/buildevents/gyptest-ninja-warnings.py b/tools/gyp/test/msvs/buildevents/gyptest-ninja-warnings.py new file mode 100644 index 00000000000000..abca89d33119b3 --- /dev/null +++ b/tools/gyp/test/msvs/buildevents/gyptest-ninja-warnings.py @@ -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 +from SConsLib 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 --git a/tools/gyp/test/msvs/buildevents/main.cc b/tools/gyp/test/msvs/buildevents/main.cc new file mode 100644 index 00000000000000..03c0285a6cc856 --- /dev/null +++ b/tools/gyp/test/msvs/buildevents/main.cc @@ -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 --git a/tools/gyp/test/msvs/config_attrs/gyptest-config_attrs.py b/tools/gyp/test/msvs/config_attrs/gyptest-config_attrs.py new file mode 100644 index 00000000000000..ee8e9a146ff999 --- /dev/null +++ b/tools/gyp/test/msvs/config_attrs/gyptest-config_attrs.py @@ -0,0 +1,41 @@ +#!/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 msvs_configuration_attributes and +msbuild_configuration_attributes are applied by using +them to set the OutputDirectory. +""" + +from __future__ import print_function + +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' + +if os.getenv('GYP_MSVS_VERSION'): + vc_version = ['VC90','VC100'][int(os.getenv('GYP_MSVS_VERSION')) >= 2010] + +expected_exe_file = os.path.join(test.workdir, vc_version, 'hello.exe') + +test.run_gyp('hello.gyp') + +test.build('hello.gyp') + +test.built_file_must_exist(expected_exe_file) + +test.pass_test() diff --git a/tools/gyp/test/msvs/config_attrs/hello.c b/tools/gyp/test/msvs/config_attrs/hello.c new file mode 100644 index 00000000000000..faadc75e2c0a59 --- /dev/null +++ b/tools/gyp/test/msvs/config_attrs/hello.c @@ -0,0 +1,11 @@ +/* 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(void) +{ + printf("Hello, world!\n"); + return 0; +} diff --git a/tools/gyp/test/msvs/config_attrs/hello.gyp b/tools/gyp/test/msvs/config_attrs/hello.gyp new file mode 100644 index 00000000000000..810a80edd8034c --- /dev/null +++ b/tools/gyp/test/msvs/config_attrs/hello.gyp @@ -0,0 +1,21 @@ +# 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': [ + 'hello.c', + ], + 'msvs_configuration_attributes': { + 'OutputDirectory':'$(SolutionDir)VC90/' + }, + 'msbuild_configuration_attributes': { + 'OutputDirectory':'$(SolutionDir)VC100/', + }, + }, + ], +} diff --git a/tools/gyp/test/msvs/express/base/base.gyp b/tools/gyp/test/msvs/express/base/base.gyp new file mode 100644 index 00000000000000..b7c9fc6d81f1e9 --- /dev/null +++ b/tools/gyp/test/msvs/express/base/base.gyp @@ -0,0 +1,22 @@ +# 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': 'a', + 'type': 'static_library', + 'sources': [ + 'a.c', + ], + }, + { + 'target_name': 'b', + 'type': 'static_library', + 'sources': [ + 'b.c', + ], + }, + ], +} diff --git a/tools/gyp/test/msvs/express/express.gyp b/tools/gyp/test/msvs/express/express.gyp new file mode 100644 index 00000000000000..917abe2cc0b170 --- /dev/null +++ b/tools/gyp/test/msvs/express/express.gyp @@ -0,0 +1,19 @@ +# 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': 'express', + 'type': 'executable', + 'dependencies': [ + 'base/base.gyp:a', + 'base/base.gyp:b', + ], + 'sources': [ + 'main.c', + ], + }, + ], +} diff --git a/tools/gyp/test/msvs/express/gyptest-express.py b/tools/gyp/test/msvs/express/gyptest-express.py new file mode 100644 index 00000000000000..54c06f664ae751 --- /dev/null +++ b/tools/gyp/test/msvs/express/gyptest-express.py @@ -0,0 +1,29 @@ +#!/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 that flat solutions get generated for Express versions of +Visual Studio. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['msvs']) + +test.run_gyp('express.gyp', '-G', 'msvs_version=2005') +test.must_contain('express.sln', '(base)') + +test.run_gyp('express.gyp', '-G', 'msvs_version=2008') +test.must_contain('express.sln', '(base)') + +test.run_gyp('express.gyp', '-G', 'msvs_version=2005e') +test.must_not_contain('express.sln', '(base)') + +test.run_gyp('express.gyp', '-G', 'msvs_version=2008e') +test.must_not_contain('express.sln', '(base)') + + +test.pass_test() diff --git a/tools/gyp/test/msvs/external_builder/external.gyp b/tools/gyp/test/msvs/external_builder/external.gyp new file mode 100644 index 00000000000000..abe5b5889c3565 --- /dev/null +++ b/tools/gyp/test/msvs/external_builder/external.gyp @@ -0,0 +1,68 @@ +# 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': { + # the test driver switches this flag when testing external builder + 'use_external_builder%': 0, + }, + 'targets': [ + { + 'target_name': 'external', + 'type': 'executable', + 'sources': [ + 'hello.cpp', + 'hello.z', + ], + 'rules': [ + { + 'rule_name': 'test_rule', + 'extension': 'z', + 'outputs': [ + 'msbuild_rule.out', + ], + 'action': [ + 'python', + 'msbuild_rule.py', + '<(RULE_INPUT_PATH)', + 'a', 'b', 'c', + ], + 'msvs_cygwin_shell': 0, + }, + ], + 'actions': [ + { + 'action_name': 'test action', + 'inputs': [ + 'msbuild_action.py', + ], + 'outputs': [ + 'msbuild_action.out', + ], + 'action': [ + 'python', + '<@(_inputs)', + 'x', 'y', 'z', + ], + 'msvs_cygwin_shell': 0, + }, + ], + 'conditions': [ + ['use_external_builder==1', { + 'msvs_external_builder': 'test', + 'msvs_external_builder_build_cmd': [ + 'python', + 'external_builder.py', + 'build', '1', '2', '3', + ], + 'msvs_external_builder_clean_cmd': [ + 'python', + 'external_builder.py', + 'clean', '4', '5', + ], + }], + ], + }, + ], +} diff --git a/tools/gyp/test/msvs/external_builder/external_builder.py b/tools/gyp/test/msvs/external_builder/external_builder.py new file mode 100644 index 00000000000000..ddfc1e5e33c10b --- /dev/null +++ b/tools/gyp/test/msvs/external_builder/external_builder.py @@ -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. + +import sys + +with open('external_builder.out', 'w') as f: + f.write(' '.join(sys.argv)) + diff --git a/tools/gyp/test/msvs/external_builder/gyptest-all.py b/tools/gyp/test/msvs/external_builder/gyptest-all.py new file mode 100644 index 00000000000000..d554d22493e252 --- /dev/null +++ b/tools/gyp/test/msvs/external_builder/gyptest-all.py @@ -0,0 +1,59 @@ +#!/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 msvs_external_builder being set will invoke the provided +msvs_external_builder_build_cmd and msvs_external_builder_clean_cmd, and will +not invoke MSBuild actions and rules. +""" + +import os +import sys +import TestGyp + +if int(os.environ.get('GYP_MSVS_VERSION', 0)) < 2010: + sys.exit(2) + +test = TestGyp.TestGyp(formats=['msvs', '!mock'], workdir='workarea_all') + +# without the flag set +test.run_gyp('external.gyp') +test.build('external.gyp', target='external') +test.must_not_exist('external_builder.out') +test.built_file_must_exist('msbuild_rule.out') +test.built_file_must_exist('msbuild_action.out') +test.must_match('msbuild_rule.out', 'msbuild_rule.py hello.z a b c') +test.must_match('msbuild_action.out', 'msbuild_action.py x y z') +os.remove('msbuild_rule.out') +os.remove('msbuild_action.out') + +# with the flag set, using Build +try: + os.environ['GYP_DEFINES'] = 'use_external_builder=1' + test.run_gyp('external.gyp') + test.build('external.gyp', target='external') +finally: + del os.environ['GYP_DEFINES'] +test.must_not_exist('msbuild_rule.out') +test.must_not_exist('msbuild_action.out') +test.must_exist('external_builder.out') +test.must_match('external_builder.out', 'external_builder.py build 1 2 3') +os.remove('external_builder.out') + +# with the flag set, using Clean +try: + os.environ['GYP_DEFINES'] = 'use_external_builder=1' + test.run_gyp('external.gyp') + test.build('external.gyp', target='external', clean=True) +finally: + del os.environ['GYP_DEFINES'] +test.must_not_exist('msbuild_rule.out') +test.must_not_exist('msbuild_action.out') +test.must_exist('external_builder.out') +test.must_match('external_builder.out', 'external_builder.py clean 4 5') +os.remove('external_builder.out') + +test.pass_test() diff --git a/tools/gyp/test/msvs/external_builder/hello.cpp b/tools/gyp/test/msvs/external_builder/hello.cpp new file mode 100644 index 00000000000000..bc0c0265b53750 --- /dev/null +++ b/tools/gyp/test/msvs/external_builder/hello.cpp @@ -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(void) { + printf("Hello, world!\n"); + return 0; +} diff --git a/tools/gyp/test/msvs/external_builder/hello.z b/tools/gyp/test/msvs/external_builder/hello.z new file mode 100644 index 00000000000000..aa478827b50f55 --- /dev/null +++ b/tools/gyp/test/msvs/external_builder/hello.z @@ -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. + +This file will be passed to the test rule. + diff --git a/tools/gyp/test/msvs/external_builder/msbuild_action.py b/tools/gyp/test/msvs/external_builder/msbuild_action.py new file mode 100644 index 00000000000000..632d786922fd52 --- /dev/null +++ b/tools/gyp/test/msvs/external_builder/msbuild_action.py @@ -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. + +import sys + +with open('msbuild_action.out', 'w') as f: + f.write(' '.join(sys.argv)) + diff --git a/tools/gyp/test/msvs/external_builder/msbuild_rule.py b/tools/gyp/test/msvs/external_builder/msbuild_rule.py new file mode 100644 index 00000000000000..0d6e315775f764 --- /dev/null +++ b/tools/gyp/test/msvs/external_builder/msbuild_rule.py @@ -0,0 +1,11 @@ +# 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 sys, os.path + +sys.argv[1] = os.path.basename(sys.argv[1]) + +with open('msbuild_rule.out', 'w') as f: + f.write(' '.join(sys.argv)) + diff --git a/tools/gyp/test/msvs/filters/filters.gyp b/tools/gyp/test/msvs/filters/filters.gyp new file mode 100644 index 00000000000000..a4106dc8eb30be --- /dev/null +++ b/tools/gyp/test/msvs/filters/filters.gyp @@ -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 --git a/tools/gyp/test/msvs/filters/gyptest-filters-2008.py b/tools/gyp/test/msvs/filters/gyptest-filters-2008.py new file mode 100644 index 00000000000000..41ca085823a9bd --- /dev/null +++ b/tools/gyp/test/msvs/filters/gyptest-filters-2008.py @@ -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 --git a/tools/gyp/test/msvs/filters/gyptest-filters-2010.py b/tools/gyp/test/msvs/filters/gyptest-filters-2010.py new file mode 100644 index 00000000000000..02f07732be2b83 --- /dev/null +++ b/tools/gyp/test/msvs/filters/gyptest-filters-2010.py @@ -0,0 +1,59 @@ +#!/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') + +required = '''\ + + + folder1 + + + folder1 + + + folder2 + + +'''.splitlines() +test.must_contain('three_files_in_two_folders.vcxproj.filters', required) + +required2 = '''\ + + + folder1\\nested + + + folder2 + + + folder1\\nested + + + folder1\\other + + +'''.splitlines() +test.must_contain('nested_folders.vcxproj.filters', required2) + + +test.pass_test() diff --git a/tools/gyp/test/msvs/list_excluded/gyptest-all.py b/tools/gyp/test/msvs/list_excluded/gyptest-all.py new file mode 100644 index 00000000000000..5a370f6b476431 --- /dev/null +++ b/tools/gyp/test/msvs/list_excluded/gyptest-all.py @@ -0,0 +1,51 @@ +#!/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 msvs_list_excluded_files=0 doesn't list files that would +normally be in _excluded_files, and that if that flag is not set, then they +are still listed. +""" + +import os +import TestGyp + +test = TestGyp.TestGyp(formats=['msvs'], workdir='workarea_all') + + +# with the flag set to 0 +try: + os.environ['GYP_GENERATOR_FLAGS'] = 'msvs_list_excluded_files=0' + test.run_gyp('hello_exclude.gyp') +finally: + del os.environ['GYP_GENERATOR_FLAGS'] +if test.uses_msbuild: + test.must_not_contain('hello.vcxproj', 'hello_mac') +else: + test.must_not_contain('hello.vcproj', 'hello_mac') + + +# with the flag not set +test.run_gyp('hello_exclude.gyp') +if test.uses_msbuild: + test.must_contain('hello.vcxproj', 'hello_mac') +else: + test.must_contain('hello.vcproj', 'hello_mac') + + +# with the flag explicitly set to 1 +try: + os.environ['GYP_GENERATOR_FLAGS'] = 'msvs_list_excluded_files=1' + test.run_gyp('hello_exclude.gyp') +finally: + del os.environ['GYP_GENERATOR_FLAGS'] +if test.uses_msbuild: + test.must_contain('hello.vcxproj', 'hello_mac') +else: + test.must_contain('hello.vcproj', 'hello_mac') + + +test.pass_test() diff --git a/tools/gyp/test/msvs/list_excluded/hello.cpp b/tools/gyp/test/msvs/list_excluded/hello.cpp new file mode 100644 index 00000000000000..bc0c0265b53750 --- /dev/null +++ b/tools/gyp/test/msvs/list_excluded/hello.cpp @@ -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(void) { + printf("Hello, world!\n"); + return 0; +} diff --git a/tools/gyp/test/msvs/list_excluded/hello_exclude.gyp b/tools/gyp/test/msvs/list_excluded/hello_exclude.gyp new file mode 100644 index 00000000000000..aa160f2367a192 --- /dev/null +++ b/tools/gyp/test/msvs/list_excluded/hello_exclude.gyp @@ -0,0 +1,19 @@ +# 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': [ + 'hello.cpp', + 'hello_mac.cpp', + ], + 'conditions': [ + ['OS!="mac"', {'sources!': ['hello_mac.cpp']}], + ] + }, + ], +} diff --git a/tools/gyp/test/msvs/list_excluded/hello_mac.cpp b/tools/gyp/test/msvs/list_excluded/hello_mac.cpp new file mode 100644 index 00000000000000..b9f6242c4b3ab5 --- /dev/null +++ b/tools/gyp/test/msvs/list_excluded/hello_mac.cpp @@ -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 hello2() { + printf("Hello, two!\n"); + return 0; +} diff --git a/tools/gyp/test/msvs/missing_sources/gyptest-missing.py b/tools/gyp/test/msvs/missing_sources/gyptest-missing.py new file mode 100644 index 00000000000000..62a99ef0f105ce --- /dev/null +++ b/tools/gyp/test/msvs/missing_sources/gyptest-missing.py @@ -0,0 +1,43 @@ +#!/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 missing 'sources' files are treated as fatal errors when the +the generator flag 'msvs_error_on_missing_sources' is set. +""" + +import TestGyp +import os +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja'], workdir='workarea_all') + + # With the flag not set + test.run_gyp('hello_missing.gyp') + + # With the flag explicitly set to 0 + try: + os.environ['GYP_GENERATOR_FLAGS'] = 'msvs_error_on_missing_sources=0' + test.run_gyp('hello_missing.gyp') + finally: + del os.environ['GYP_GENERATOR_FLAGS'] + + # With the flag explicitly set to 1 + try: + os.environ['GYP_GENERATOR_FLAGS'] = 'msvs_error_on_missing_sources=1' + # Test to make sure GYP raises an exception (exit status 1). Since this will + # also print a backtrace, ensure that TestGyp is not checking that stderr is + # empty by specifying None, which means do not perform any checking. + # Instead, stderr is checked below to ensure it contains the expected + # output. + test.run_gyp('hello_missing.gyp', status=1, stderr=None) + finally: + del os.environ['GYP_GENERATOR_FLAGS'] + test.must_contain_any_line(test.stderr(), + ["Missing input files:"]) + + test.pass_test() diff --git a/tools/gyp/test/msvs/missing_sources/hello_missing.gyp b/tools/gyp/test/msvs/missing_sources/hello_missing.gyp new file mode 100644 index 00000000000000..c08926bbff4ea3 --- /dev/null +++ b/tools/gyp/test/msvs/missing_sources/hello_missing.gyp @@ -0,0 +1,15 @@ +# 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': [ + 'hello_missing.cpp', + ], + }, + ], +} diff --git a/tools/gyp/test/msvs/multiple_actions_error_handling/action_fail.py b/tools/gyp/test/msvs/multiple_actions_error_handling/action_fail.py new file mode 100644 index 00000000000000..286fc4e1329aa9 --- /dev/null +++ b/tools/gyp/test/msvs/multiple_actions_error_handling/action_fail.py @@ -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 --git a/tools/gyp/test/msvs/multiple_actions_error_handling/action_succeed.py b/tools/gyp/test/msvs/multiple_actions_error_handling/action_succeed.py new file mode 100644 index 00000000000000..35543731976775 --- /dev/null +++ b/tools/gyp/test/msvs/multiple_actions_error_handling/action_succeed.py @@ -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 --git a/tools/gyp/test/msvs/multiple_actions_error_handling/actions.gyp b/tools/gyp/test/msvs/multiple_actions_error_handling/actions.gyp new file mode 100644 index 00000000000000..ab99e929e24966 --- /dev/null +++ b/tools/gyp/test/msvs/multiple_actions_error_handling/actions.gyp @@ -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 --git a/tools/gyp/test/msvs/multiple_actions_error_handling/gyptest.py b/tools/gyp/test/msvs/multiple_actions_error_handling/gyptest.py new file mode 100644 index 00000000000000..9493b3cafebda1 --- /dev/null +++ b/tools/gyp/test/msvs/multiple_actions_error_handling/gyptest.py @@ -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 failing actions make the build fail reliably, even when there +are multiple actions in one project. +""" + +import TestGyp +from SConsLib 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 --git a/tools/gyp/test/msvs/props/AppName.props b/tools/gyp/test/msvs/props/AppName.props new file mode 100644 index 00000000000000..b688f663d58813 --- /dev/null +++ b/tools/gyp/test/msvs/props/AppName.props @@ -0,0 +1,14 @@ + + + + Greet + + + <_ProjectFileVersion>10.0.40219.1 + + + + $(AppName) + + + diff --git a/tools/gyp/test/msvs/props/AppName.vsprops b/tools/gyp/test/msvs/props/AppName.vsprops new file mode 100644 index 00000000000000..84b9af3800c620 --- /dev/null +++ b/tools/gyp/test/msvs/props/AppName.vsprops @@ -0,0 +1,11 @@ + + + + diff --git a/tools/gyp/test/msvs/props/gyptest-props.py b/tools/gyp/test/msvs/props/gyptest-props.py new file mode 100644 index 00000000000000..abd4df2241e267 --- /dev/null +++ b/tools/gyp/test/msvs/props/gyptest-props.py @@ -0,0 +1,22 @@ +#!/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 props files are added by using a +props file to set the name of the built executable. +""" + +import TestGyp + +test = TestGyp.TestGyp(workdir='workarea_all', formats=['msvs']) + +test.run_gyp('hello.gyp') + +test.build('hello.gyp') + +test.built_file_must_exist('Greet.exe') + +test.pass_test() diff --git a/tools/gyp/test/msvs/props/hello.c b/tools/gyp/test/msvs/props/hello.c new file mode 100644 index 00000000000000..faadc75e2c0a59 --- /dev/null +++ b/tools/gyp/test/msvs/props/hello.c @@ -0,0 +1,11 @@ +/* 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(void) +{ + printf("Hello, world!\n"); + return 0; +} diff --git a/tools/gyp/test/msvs/props/hello.gyp b/tools/gyp/test/msvs/props/hello.gyp new file mode 100644 index 00000000000000..5a58317fa7bdb9 --- /dev/null +++ b/tools/gyp/test/msvs/props/hello.gyp @@ -0,0 +1,22 @@ +# 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', + 'product_name': '$(AppName)', + 'type': 'executable', + 'sources': [ + 'hello.c', + ], + 'msvs_props': [ + '$(SolutionDir)AppName.vsprops' + ], + 'msbuild_props': [ + '$(SolutionDir)AppName.props' + ], + }, + ], +} + diff --git a/tools/gyp/test/msvs/rules_stdout_stderr/dummy.bar b/tools/gyp/test/msvs/rules_stdout_stderr/dummy.bar new file mode 100644 index 00000000000000..25178696d2bad7 --- /dev/null +++ b/tools/gyp/test/msvs/rules_stdout_stderr/dummy.bar @@ -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 --git a/tools/gyp/test/msvs/rules_stdout_stderr/dummy.foo b/tools/gyp/test/msvs/rules_stdout_stderr/dummy.foo new file mode 100644 index 00000000000000..6a7990bb98c127 --- /dev/null +++ b/tools/gyp/test/msvs/rules_stdout_stderr/dummy.foo @@ -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 --git a/tools/gyp/test/msvs/rules_stdout_stderr/gyptest-rules-stdout-stderr.py b/tools/gyp/test/msvs/rules_stdout_stderr/gyptest-rules-stdout-stderr.py new file mode 100644 index 00000000000000..d46062a4d8ac4b --- /dev/null +++ b/tools/gyp/test/msvs/rules_stdout_stderr/gyptest-rules-stdout-stderr.py @@ -0,0 +1,32 @@ +#!/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 not sys.platform == 'win32': + exit(2) + +test = TestGyp.TestGyp(formats=['msvs']) + +test.run_gyp('rules-stdout-stderr.gyp') +test.must_contain('test.vcxproj', 'test.targets') + +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.build('rules-stdout-stderr.gyp', test.ALL) +test.must_contain_all_lines(test.stdout(), expected_stdout_lines) + +test.pass_test() diff --git a/tools/gyp/test/msvs/rules_stdout_stderr/rule_stderr.py b/tools/gyp/test/msvs/rules_stdout_stderr/rule_stderr.py new file mode 100644 index 00000000000000..2081513ec88376 --- /dev/null +++ b/tools/gyp/test/msvs/rules_stdout_stderr/rule_stderr.py @@ -0,0 +1,8 @@ +#!/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. + +from __future__ import print_function +import sys +print("This will go to stderr", file=sys.stderr) diff --git a/tools/gyp/test/msvs/rules_stdout_stderr/rule_stdout.py b/tools/gyp/test/msvs/rules_stdout_stderr/rule_stdout.py new file mode 100644 index 00000000000000..4c073ebc4537be --- /dev/null +++ b/tools/gyp/test/msvs/rules_stdout_stderr/rule_stdout.py @@ -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. + +from __future__ import print_function +print("This will go to stdout") diff --git a/tools/gyp/test/msvs/rules_stdout_stderr/rules-stdout-stderr.gyp b/tools/gyp/test/msvs/rules_stdout_stderr/rules-stdout-stderr.gyp new file mode 100644 index 00000000000000..ce93643f8e7ef3 --- /dev/null +++ b/tools/gyp/test/msvs/rules_stdout_stderr/rules-stdout-stderr.gyp @@ -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 --git a/tools/gyp/test/msvs/shared_output/common.gypi b/tools/gyp/test/msvs/shared_output/common.gypi new file mode 100644 index 00000000000000..c6fa341d68ca09 --- /dev/null +++ b/tools/gyp/test/msvs/shared_output/common.gypi @@ -0,0 +1,17 @@ +# 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. + +{ + 'target_defaults': { + 'default_configuration': 'Baz', + 'configurations': { + 'Baz': { + 'msvs_configuration_attributes': { + 'OutputDirectory': '<(DEPTH)/foo', + 'IntermediateDirectory': '$(OutDir)/bar', + }, + }, + }, + }, +} diff --git a/tools/gyp/test/msvs/shared_output/gyptest-shared_output.py b/tools/gyp/test/msvs/shared_output/gyptest-shared_output.py new file mode 100644 index 00000000000000..201efedc3285e7 --- /dev/null +++ b/tools/gyp/test/msvs/shared_output/gyptest-shared_output.py @@ -0,0 +1,39 @@ +#!/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. + +""" +Test checking that IntermediateDirectory can be defined in terms of +OutputDirectory. We previously had emitted the definition of +IntermediateDirectory before the definition of OutputDirectory. +This is required so that $(IntDir) can be based on $(OutDir). +""" + +import TestGyp +import os + +# NOTE: This test really is vcbuild/msbuild specific (not applicable to windows +# ninja), as it is testing the msvs output location when opening an .sln +# other than all.sln. +test = TestGyp.TestGyp(workdir='workarea_shared_output', formats=['msvs']) + +test.run_gyp('hello.gyp') +test.set_configuration('Baz') + +test.build('there/there.gyp', test.ALL) +test.must_exist(test.built_file_path('foo/there.exe')) +test.must_exist(test.built_file_path('foo/bar/there.obj')) + +test.build('hello.gyp', test.ALL) +test.must_exist(test.built_file_path('foo/hello.exe')) +test.must_exist(test.built_file_path('foo/bar/hello.obj')) + +if test.format == 'msvs': + if test.uses_msbuild: + test.must_contain('pull_in_there.vcxproj', '$(OutDir)bar\\') + else: + test.must_contain('pull_in_there.vcproj', 'IntermediateDirectory="$(OutDir)bar\\"') + +test.pass_test() diff --git a/tools/gyp/test/msvs/shared_output/hello.c b/tools/gyp/test/msvs/shared_output/hello.c new file mode 100644 index 00000000000000..698e4fd36c3f4b --- /dev/null +++ b/tools/gyp/test/msvs/shared_output/hello.c @@ -0,0 +1,12 @@ +/* + * 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(void) { + printf("Hello, world!\n"); + return 0; +} diff --git a/tools/gyp/test/msvs/shared_output/hello.gyp b/tools/gyp/test/msvs/shared_output/hello.gyp new file mode 100644 index 00000000000000..f80e5cfca1d0f4 --- /dev/null +++ b/tools/gyp/test/msvs/shared_output/hello.gyp @@ -0,0 +1,21 @@ +# 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. + +{ + 'includes': ['common.gypi'], + 'targets': [ + { + 'target_name': 'pull_in_there', + 'type': 'none', + 'dependencies': ['there/there.gyp:*'], + }, + { + 'target_name': 'hello', + 'type': 'executable', + 'sources': [ + 'hello.c', + ], + }, + ], +} diff --git a/tools/gyp/test/msvs/shared_output/there/there.c b/tools/gyp/test/msvs/shared_output/there/there.c new file mode 100644 index 00000000000000..698e4fd36c3f4b --- /dev/null +++ b/tools/gyp/test/msvs/shared_output/there/there.c @@ -0,0 +1,12 @@ +/* + * 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(void) { + printf("Hello, world!\n"); + return 0; +} diff --git a/tools/gyp/test/msvs/shared_output/there/there.gyp b/tools/gyp/test/msvs/shared_output/there/there.gyp new file mode 100644 index 00000000000000..56feff326ce37a --- /dev/null +++ b/tools/gyp/test/msvs/shared_output/there/there.gyp @@ -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. + +{ + 'includes': ['../common.gypi'], + 'targets': [ + { + 'target_name': 'there', + 'type': 'executable', + 'sources': [ + 'there.c', + ], + }, + ], +} diff --git a/tools/gyp/test/msvs/uldi2010/gyptest-all.py b/tools/gyp/test/msvs/uldi2010/gyptest-all.py new file mode 100644 index 00000000000000..cc248fbd635c49 --- /dev/null +++ b/tools/gyp/test/msvs/uldi2010/gyptest-all.py @@ -0,0 +1,20 @@ +#!/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 uldi can be disabled on a per-project-reference basis in vs2010. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['msvs'], workdir='workarea_all') + +test.run_gyp('hello.gyp') + +if test.uses_msbuild: + test.must_contain('hello.vcxproj', 'false') + +test.pass_test() diff --git a/tools/gyp/test/msvs/uldi2010/hello.c b/tools/gyp/test/msvs/uldi2010/hello.c new file mode 100644 index 00000000000000..06e6a029052bf7 --- /dev/null +++ b/tools/gyp/test/msvs/uldi2010/hello.c @@ -0,0 +1,13 @@ +/* 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 + +extern int hello2(); + +int main(void) { + printf("Hello, world!\n"); + hello2(); + return 0; +} diff --git a/tools/gyp/test/msvs/uldi2010/hello.gyp b/tools/gyp/test/msvs/uldi2010/hello.gyp new file mode 100644 index 00000000000000..a2bf2badb18fcc --- /dev/null +++ b/tools/gyp/test/msvs/uldi2010/hello.gyp @@ -0,0 +1,26 @@ +# 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': [ + 'hello.c', + ], + 'dependencies': [ + 'hellolib', + ] + }, + { + 'target_name': 'hellolib', + 'type': 'static_library', + 'sources': [ + 'hello2.c', + ], + 'msvs_2010_disable_uldi_when_referenced': 1, + }, + ], +} diff --git a/tools/gyp/test/msvs/uldi2010/hello2.c b/tools/gyp/test/msvs/uldi2010/hello2.c new file mode 100644 index 00000000000000..e2f23238d1648d --- /dev/null +++ b/tools/gyp/test/msvs/uldi2010/hello2.c @@ -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 hello2() { + printf("Hello, two!\n"); + return 0; +} diff --git a/tools/gyp/test/multiple-targets/gyptest-all.py b/tools/gyp/test/multiple-targets/gyptest-all.py new file mode 100644 index 00000000000000..3ef50090d1a0c8 --- /dev/null +++ b/tools/gyp/test/multiple-targets/gyptest-all.py @@ -0,0 +1,30 @@ +#!/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 TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('multiple.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('multiple.gyp', test.ALL, chdir='relocate/src', stderr=None) + +expect1 = """\ +hello from prog1.c +hello from common.c +""" + +expect2 = """\ +hello from prog2.c +hello from common.c +""" + +test.run_built_executable('prog1', stdout=expect1, chdir='relocate/src') +test.run_built_executable('prog2', stdout=expect2, chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/multiple-targets/gyptest-default.py b/tools/gyp/test/multiple-targets/gyptest-default.py new file mode 100644 index 00000000000000..db15d794c376f0 --- /dev/null +++ b/tools/gyp/test/multiple-targets/gyptest-default.py @@ -0,0 +1,30 @@ +#!/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 TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('multiple.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('multiple.gyp', chdir='relocate/src') + +expect1 = """\ +hello from prog1.c +hello from common.c +""" + +expect2 = """\ +hello from prog2.c +hello from common.c +""" + +test.run_built_executable('prog1', stdout=expect1, chdir='relocate/src') +test.run_built_executable('prog2', stdout=expect2, chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/multiple-targets/src/common.c b/tools/gyp/test/multiple-targets/src/common.c new file mode 100644 index 00000000000000..f1df7c1431464b --- /dev/null +++ b/tools/gyp/test/multiple-targets/src/common.c @@ -0,0 +1,7 @@ +#include + +void common(void) +{ + printf("hello from common.c\n"); + return; +} diff --git a/tools/gyp/test/multiple-targets/src/multiple.gyp b/tools/gyp/test/multiple-targets/src/multiple.gyp new file mode 100644 index 00000000000000..3db4ea30cd0b29 --- /dev/null +++ b/tools/gyp/test/multiple-targets/src/multiple.gyp @@ -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': 'prog1', + 'type': 'executable', + 'sources': [ + 'prog1.c', + 'common.c', + ], + }, + { + 'target_name': 'prog2', + 'type': 'executable', + 'sources': [ + 'prog2.c', + 'common.c', + ], + }, + ], +} diff --git a/tools/gyp/test/multiple-targets/src/prog1.c b/tools/gyp/test/multiple-targets/src/prog1.c new file mode 100644 index 00000000000000..fbf8d4cd7cce14 --- /dev/null +++ b/tools/gyp/test/multiple-targets/src/prog1.c @@ -0,0 +1,10 @@ +#include + +extern void common(void); + +int main(void) +{ + printf("hello from prog1.c\n"); + common(); + return 0; +} diff --git a/tools/gyp/test/multiple-targets/src/prog2.c b/tools/gyp/test/multiple-targets/src/prog2.c new file mode 100644 index 00000000000000..a94b5c155ed0db --- /dev/null +++ b/tools/gyp/test/multiple-targets/src/prog2.c @@ -0,0 +1,10 @@ +#include + +extern void common(void); + +int main(void) +{ + printf("hello from prog2.c\n"); + common(); + return 0; +} diff --git a/tools/gyp/test/ninja/action-rule-hash/gyptest-action-rule-hash.py b/tools/gyp/test/ninja/action-rule-hash/gyptest-action-rule-hash.py new file mode 100644 index 00000000000000..7147fd2fc31ac6 --- /dev/null +++ b/tools/gyp/test/ninja/action-rule-hash/gyptest-action-rule-hash.py @@ -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 --git a/tools/gyp/test/ninja/action-rule-hash/subdir/action-rule-hash.gyp b/tools/gyp/test/ninja/action-rule-hash/subdir/action-rule-hash.gyp new file mode 100644 index 00000000000000..0e88a3019fa881 --- /dev/null +++ b/tools/gyp/test/ninja/action-rule-hash/subdir/action-rule-hash.gyp @@ -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 --git a/tools/gyp/test/ninja/action-rule-hash/subdir/emit.py b/tools/gyp/test/ninja/action-rule-hash/subdir/emit.py new file mode 100644 index 00000000000000..6b1712557450a1 --- /dev/null +++ b/tools/gyp/test/ninja/action-rule-hash/subdir/emit.py @@ -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], 'w') +f.write('int main() {\n') +f.write(' return 0;\n') +f.write('}\n') +f.close() diff --git a/tools/gyp/test/ninja/action_dependencies/gyptest-action-dependencies.py b/tools/gyp/test/ninja/action_dependencies/gyptest-action-dependencies.py new file mode 100644 index 00000000000000..89813bab17e318 --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/gyptest-action-dependencies.py @@ -0,0 +1,64 @@ +#!/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 building an object file correctly depends on running actions in +dependent targets, but not the targets themselves. +""" + +from __future__ import print_function + +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: +# - it explicitly tests the optimization, which is not implemented (yet?) on +# other generators +# - it relies on the exact path to output object files, which is generator +# dependent, and actually, relies on the ability to build only that object file, +# 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') + +chdir = 'relocate/src' +test.relocate('src', chdir) + +objext = '.obj' if sys.platform == 'win32' else '.o' + +test.build('action_dependencies.gyp', + os.path.join('obj', 'b.b' + objext), + chdir=chdir) + +# The 'a' actions should be run (letting b.c compile), but the a static library +# should not be built. +test.built_file_must_not_exist('a', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_not_exist('b', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_exist(os.path.join('obj', 'b.b' + objext), chdir=chdir) + +test.build('action_dependencies.gyp', + os.path.join('obj', 'c.c' + objext), + chdir=chdir) + +# 'a' and 'b' should be built, so that the 'c' action succeeds, letting c.c +# compile +test.built_file_must_exist('a', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_exist('b', type=test.EXECUTABLE, chdir=chdir) +test.built_file_must_exist(os.path.join('obj', 'c.c' + objext), chdir=chdir) + + +test.pass_test() diff --git a/tools/gyp/test/ninja/action_dependencies/src/a.c b/tools/gyp/test/ninja/action_dependencies/src/a.c new file mode 100644 index 00000000000000..4d7af9b26ca50d --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/src/a.c @@ -0,0 +1,10 @@ +/* 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. + */ + +#include "a.h" + +int funcA() { + return 42; +} diff --git a/tools/gyp/test/ninja/action_dependencies/src/a.h b/tools/gyp/test/ninja/action_dependencies/src/a.h new file mode 100644 index 00000000000000..335db5673985db --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/src/a.h @@ -0,0 +1,13 @@ +/* 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. + */ + +#ifndef A_H_ +#define A_H_ + +#include "a/generated.h" + +int funcA(); + +#endif // A_H_ diff --git a/tools/gyp/test/ninja/action_dependencies/src/action_dependencies.gyp b/tools/gyp/test/ninja/action_dependencies/src/action_dependencies.gyp new file mode 100644 index 00000000000000..5baa7a7d47e334 --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/src/action_dependencies.gyp @@ -0,0 +1,88 @@ +# 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': 'a', + 'type': 'static_library', + 'sources': [ + 'a.c', + 'a.h', + ], + 'actions': [ + { + 'action_name': 'generate_headers', + 'inputs': [ + 'emit.py' + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/a/generated.h' + ], + 'action': [ + 'python', + 'emit.py', + '<(SHARED_INTERMEDIATE_DIR)/a/generated.h', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + }, + }, + { + 'target_name': 'b', + 'type': 'executable', + 'sources': [ + 'b.c', + 'b.h', + ], + 'dependencies': [ + 'a', + ], + }, + { + 'target_name': 'c', + 'type': 'static_library', + 'sources': [ + 'c.c', + 'c.h', + ], + 'dependencies': [ + 'b', + ], + 'actions': [ + { + 'action_name': 'generate_headers', + 'inputs': [ + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/c/generated.h' + ], + 'action': [ + '<(PRODUCT_DIR)/b', + '<(SHARED_INTERMEDIATE_DIR)/c/generated.h', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + }, + }, + ], +} diff --git a/tools/gyp/test/ninja/action_dependencies/src/b.c b/tools/gyp/test/ninja/action_dependencies/src/b.c new file mode 100644 index 00000000000000..824464695a8617 --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/src/b.c @@ -0,0 +1,18 @@ +/* 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 + +#include "b.h" + +int main(int argc, char** argv) { + FILE* f; + if (argc < 2) + return 1; + f = fopen(argv[1], "wt"); + fprintf(f, "#define VALUE %d\n", funcA()); + fclose(f); + return 0; +} diff --git a/tools/gyp/test/ninja/action_dependencies/src/b.h b/tools/gyp/test/ninja/action_dependencies/src/b.h new file mode 100644 index 00000000000000..91362cd8997311 --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/src/b.h @@ -0,0 +1,13 @@ +/* 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. + */ + +#ifndef B_H_ +#define B_H_ + +#include "a.h" + +int funcB(); + +#endif // B_H_ diff --git a/tools/gyp/test/ninja/action_dependencies/src/c.c b/tools/gyp/test/ninja/action_dependencies/src/c.c new file mode 100644 index 00000000000000..b412087ec870e3 --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/src/c.c @@ -0,0 +1,10 @@ +/* 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. + */ + +#include "c.h" + +int funcC() { + return VALUE; +} diff --git a/tools/gyp/test/ninja/action_dependencies/src/c.h b/tools/gyp/test/ninja/action_dependencies/src/c.h new file mode 100644 index 00000000000000..c81a45bbe76fe6 --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/src/c.h @@ -0,0 +1,13 @@ +/* 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. + */ + +#ifndef C_H_ +#define C_H_ + +#include "c/generated.h" + +int funcC(); + +#endif // C_H_ diff --git a/tools/gyp/test/ninja/action_dependencies/src/emit.py b/tools/gyp/test/ninja/action_dependencies/src/emit.py new file mode 100644 index 00000000000000..8ed12f7393bfa6 --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/src/emit.py @@ -0,0 +1,11 @@ +#!/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. + +import sys + +f = open(sys.argv[1], 'w') +f.write('/* Hello World */\n') +f.close() diff --git a/tools/gyp/test/ninja/chained-dependency/chained-dependency.gyp b/tools/gyp/test/ninja/chained-dependency/chained-dependency.gyp new file mode 100644 index 00000000000000..3fe68ae85a7ffc --- /dev/null +++ b/tools/gyp/test/ninja/chained-dependency/chained-dependency.gyp @@ -0,0 +1,53 @@ +# Copyright (c) 2010 Google 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 first target generates a header. + { + 'target_name': 'generate_header', + 'type': 'none', + 'msvs_cygwin_shell': '0', + 'actions': [ + { + 'action_name': 'generate header', + 'inputs': [], + 'outputs': ['<(SHARED_INTERMEDIATE_DIR)/generated/header.h'], + 'action': [ + 'python', '-c', 'open(<(_outputs), "w")' + ] + }, + ], + 'all_dependent_settings': { + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + }, + }, + + # This intermediate target does nothing other than pull in a + # dependency on the above generated target. + { + 'target_name': 'chain', + 'type': 'none', + 'dependencies': [ + 'generate_header', + ], + }, + + # This final target is: + # - a static library (so gyp doesn't transitively pull in dependencies); + # - that relies on the generated file two dependencies away. + { + 'target_name': 'chained', + 'type': 'static_library', + 'dependencies': [ + 'chain', + ], + 'sources': [ + 'chained.c', + ], + }, + ], +} diff --git a/tools/gyp/test/ninja/chained-dependency/chained.c b/tools/gyp/test/ninja/chained-dependency/chained.c new file mode 100644 index 00000000000000..c1ff1a7b12010b --- /dev/null +++ b/tools/gyp/test/ninja/chained-dependency/chained.c @@ -0,0 +1,5 @@ +#include "generated/header.h" + +int main(void) { + return 0; +} diff --git a/tools/gyp/test/ninja/chained-dependency/gyptest-chained-dependency.py b/tools/gyp/test/ninja/chained-dependency/gyptest-chained-dependency.py new file mode 100644 index 00000000000000..d8763f1d3db5b4 --- /dev/null +++ b/tools/gyp/test/ninja/chained-dependency/gyptest-chained-dependency.py @@ -0,0 +1,30 @@ +#!/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 files generated by two-steps-removed actions are built before +dependent compile steps. +""" + +import os +import sys +import TestGyp + +# This test is Ninja-specific in that: +# - the bug only showed nondeterministically in parallel builds; +# - 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', + os.path.join('obj', 'chained.chained' + objext)) +# The test passes if the .o file builds successfully. +test.pass_test() diff --git a/tools/gyp/test/ninja/empty-and-non-empty-duplicate-name/gyptest-empty-and-non-empty-duplicate-name.py b/tools/gyp/test/ninja/empty-and-non-empty-duplicate-name/gyptest-empty-and-non-empty-duplicate-name.py new file mode 100644 index 00000000000000..0bdca66cdcc794 --- /dev/null +++ b/tools/gyp/test/ninja/empty-and-non-empty-duplicate-name/gyptest-empty-and-non-empty-duplicate-name.py @@ -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 --git a/tools/gyp/test/ninja/empty-and-non-empty-duplicate-name/subdir/included.gyp b/tools/gyp/test/ninja/empty-and-non-empty-duplicate-name/subdir/included.gyp new file mode 100644 index 00000000000000..1b9fc42f3f4719 --- /dev/null +++ b/tools/gyp/test/ninja/empty-and-non-empty-duplicate-name/subdir/included.gyp @@ -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 --git a/tools/gyp/test/ninja/empty-and-non-empty-duplicate-name/test.gyp b/tools/gyp/test/ninja/empty-and-non-empty-duplicate-name/test.gyp new file mode 100644 index 00000000000000..9aa6287c7c9318 --- /dev/null +++ b/tools/gyp/test/ninja/empty-and-non-empty-duplicate-name/test.gyp @@ -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 --git a/tools/gyp/test/ninja/normalize-paths-win/gyptest-normalize-paths.py b/tools/gyp/test/ninja/normalize-paths-win/gyptest-normalize-paths.py new file mode 100644 index 00000000000000..f56dbe5921e2e8 --- /dev/null +++ b/tools/gyp/test/ninja/normalize-paths-win/gyptest-normalize-paths.py @@ -0,0 +1,46 @@ +#!/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. + +""" +Make sure paths are normalized with VS macros properly expanded on Windows. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['ninja']) + + test.run_gyp('normalize-paths.gyp') + + # We can't use existence tests because any case will pass, so we check the + # contents of ninja files directly since that's what we're most concerned + # with anyway. + subninja = open(test.built_file_path('obj/some_target.ninja')).read() + if '$!product_dir' in subninja: + test.fail_test() + if 'out\\Default' in subninja: + test.fail_test() + + second = open(test.built_file_path('obj/second.ninja')).read() + if ('..\\..\\things\\AnotherName.exe' in second or + '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() + if '..\\..\\SomethingElse' in action or 'SomethingElse' not in action: + test.fail_test() + if '..\\..\\SomeOtherInput' in action or 'SomeOtherInput' not in action: + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/ninja/normalize-paths-win/hello.cc b/tools/gyp/test/ninja/normalize-paths-win/hello.cc new file mode 100644 index 00000000000000..1711567ef56670 --- /dev/null +++ b/tools/gyp/test/ninja/normalize-paths-win/hello.cc @@ -0,0 +1,7 @@ +// 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. + +int main() { + return 0; +} diff --git a/tools/gyp/test/ninja/normalize-paths-win/normalize-paths.gyp b/tools/gyp/test/ninja/normalize-paths-win/normalize-paths.gyp new file mode 100644 index 00000000000000..544d06456d91cc --- /dev/null +++ b/tools/gyp/test/ninja/normalize-paths-win/normalize-paths.gyp @@ -0,0 +1,68 @@ +# Copyright (c) 2010 Google 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': 'Some_Target', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '<(PRODUCT_DIR)/stuff/AnotherName.exe', + }, + }, + 'sources': [ + 'HeLLo.cc', + 'blOrP.idl', + ], + }, + { + 'target_name': 'second', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(OutDir)\\things\\AnotherName.exe', + }, + }, + 'sources': [ + 'HeLLo.cc', + ], + }, + { + 'target_name': 'Copy_Target', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)', + 'files': [ + '$(VSInstallDir)\\bin\\cl.exe', + ], + }, + ], + }, + { + 'target_name': 'action', + 'type': 'none', + 'msvs_cygwin_shell': '0', + 'actions': [ + { + 'inputs': [ + '$(IntDir)\\SomeInput', + '$(OutDir)\\SomeOtherInput', + ], + 'outputs': [ + '<(PRODUCT_DIR)/ReSuLt', + '<(SHARED_INTERMEDIATE_DIR)/TempFile', + '$(OutDir)\SomethingElse', + ], + 'action_name': 'Test action', + # Unfortunately, we can't normalize this field because it's + # free-form. Fortunately, ninja doesn't inspect it at all (only the + # inputs and outputs) so it's not mandatory. + 'action': [], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/ninja/s-needs-no-depfiles/empty.s b/tools/gyp/test/ninja/s-needs-no-depfiles/empty.s new file mode 100644 index 00000000000000..218d8921e515dd --- /dev/null +++ b/tools/gyp/test/ninja/s-needs-no-depfiles/empty.s @@ -0,0 +1 @@ +# This file intentionally left blank. diff --git a/tools/gyp/test/ninja/s-needs-no-depfiles/gyptest-s-needs-no-depfiles.py b/tools/gyp/test/ninja/s-needs-no-depfiles/gyptest-s-needs-no-depfiles.py new file mode 100644 index 00000000000000..cb509be9980ada --- /dev/null +++ b/tools/gyp/test/ninja/s-needs-no-depfiles/gyptest-s-needs-no-depfiles.py @@ -0,0 +1,41 @@ +#!/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 .s files don't always trigger a rebuild, as would happen if depfiles +were used for them (since clang & gcc ignore -MMD when building .s->.o on +linux). +""" + +import os +import sys +import TestGyp + +# NOTE(fischman): Each generator uses depfiles (or not) differently, so this is +# a ninja-specific test. +test = TestGyp.TestGyp(formats=['ninja']) + +if sys.platform == 'win32' or sys.platform == 'win64': + # This test is about clang/gcc vs. depfiles; VS gets a pass. + test.pass_test() + sys.exit(0) + +test.run_gyp('s-needs-no-depfiles.gyp') + +# Build the library, grab its timestamp, rebuild the library, ensure timestamp +# hasn't changed. +test.build('s-needs-no-depfiles.gyp', 'empty') +empty_dll = test.built_file_path('empty', test.SHARED_LIB) +test.built_file_must_exist(empty_dll) +pre_stat = os.stat(test.built_file_path(empty_dll)) +test.sleep() +test.build('s-needs-no-depfiles.gyp', 'empty') +post_stat = os.stat(test.built_file_path(empty_dll)) + +if pre_stat.st_mtime != post_stat.st_mtime: + test.fail_test() +else: + test.pass_test() diff --git a/tools/gyp/test/ninja/s-needs-no-depfiles/s-needs-no-depfiles.gyp b/tools/gyp/test/ninja/s-needs-no-depfiles/s-needs-no-depfiles.gyp new file mode 100644 index 00000000000000..bd66b1a70a82c3 --- /dev/null +++ b/tools/gyp/test/ninja/s-needs-no-depfiles/s-needs-no-depfiles.gyp @@ -0,0 +1,13 @@ +# 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': 'empty', + 'type': 'shared_library', + 'sources': [ 'empty.s' ], + }, + ], +} diff --git a/tools/gyp/test/ninja/solibs_avoid_relinking/gyptest-solibs-avoid-relinking.py b/tools/gyp/test/ninja/solibs_avoid_relinking/gyptest-solibs-avoid-relinking.py new file mode 100644 index 00000000000000..e90171a0350541 --- /dev/null +++ b/tools/gyp/test/ninja/solibs_avoid_relinking/gyptest-solibs-avoid-relinking.py @@ -0,0 +1,47 @@ +#!/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 relinking a solib doesn't relink a dependent executable if the +solib's public API hasn't changed. +""" + +from __future__ import print_function + +import os +from SConsLib import TestCommon +import TestGyp + +# NOTE(fischman): This test will not work with other generators because the +# API-hash-based-mtime-preservation optimization is only implemented in +# ninja.py. It could be extended to the make.py generator as well pretty +# easily, probably. +# (also, it tests ninja-specific out paths, which would have to be generalized +# 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 +# executable, ensure timestamp hasn't changed. +test.build('solibs_avoid_relinking.gyp', 'b') +test.built_file_must_exist('b' + TestCommon.exe_suffix) +pre_stat = os.stat(test.built_file_path('b' + TestCommon.exe_suffix)) +os.utime(os.path.join(test.workdir, 'solib.cc'), + (pre_stat.st_atime, pre_stat.st_mtime + 100)) +test.sleep() +test.build('solibs_avoid_relinking.gyp', 'b') +post_stat = os.stat(test.built_file_path('b' + TestCommon.exe_suffix)) + +if pre_stat.st_mtime != post_stat.st_mtime: + test.fail_test() +else: + test.pass_test() diff --git a/tools/gyp/test/ninja/solibs_avoid_relinking/main.cc b/tools/gyp/test/ninja/solibs_avoid_relinking/main.cc new file mode 100644 index 00000000000000..2cd74d3c770a98 --- /dev/null +++ b/tools/gyp/test/ninja/solibs_avoid_relinking/main.cc @@ -0,0 +1,5 @@ +extern int foo(); + +int main() { + return foo(); +} diff --git a/tools/gyp/test/ninja/solibs_avoid_relinking/solib.cc b/tools/gyp/test/ninja/solibs_avoid_relinking/solib.cc new file mode 100644 index 00000000000000..0856cd4e007b2e --- /dev/null +++ b/tools/gyp/test/ninja/solibs_avoid_relinking/solib.cc @@ -0,0 +1,8 @@ +#ifdef _MSC_VER +__declspec(dllexport) +#else +__attribute__((visibility("default"))) +#endif +int foo() { + return 42; +} diff --git a/tools/gyp/test/ninja/solibs_avoid_relinking/solibs_avoid_relinking.gyp b/tools/gyp/test/ninja/solibs_avoid_relinking/solibs_avoid_relinking.gyp new file mode 100644 index 00000000000000..e816351d684f55 --- /dev/null +++ b/tools/gyp/test/ninja/solibs_avoid_relinking/solibs_avoid_relinking.gyp @@ -0,0 +1,38 @@ +# 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': 'a', + 'type': 'shared_library', + 'sources': [ 'solib.cc' ], + # Incremental linking enabled so that .lib timestamp is maintained when + # exports are unchanged. + 'msvs_settings': { + 'VCLinkerTool': { + 'LinkIncremental': '2', + } + }, + }, + { + 'target_name': 'b', + 'type': 'executable', + 'sources': [ 'main.cc' ], + 'dependencies': [ 'a' ], + 'msvs_settings': { + 'VCLinkerTool': { + 'LinkIncremental': '2', + } + }, + }, + ], + 'conditions': [ + ['OS=="linux"', { + 'target_defaults': { + 'cflags': ['-fPIC'], + }, + }], + ], +} diff --git a/tools/gyp/test/ninja/use-console/foo.bar b/tools/gyp/test/ninja/use-console/foo.bar new file mode 100644 index 00000000000000..07c476a8664bbf --- /dev/null +++ b/tools/gyp/test/ninja/use-console/foo.bar @@ -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 --git a/tools/gyp/test/ninja/use-console/gyptest-use-console.py b/tools/gyp/test/ninja/use-console/gyptest-use-console.py new file mode 100644 index 00000000000000..f76fcd98296eae --- /dev/null +++ b/tools/gyp/test/ninja/use-console/gyptest-use-console.py @@ -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 --git a/tools/gyp/test/ninja/use-console/use-console.gyp b/tools/gyp/test/ninja/use-console/use-console.gyp new file mode 100644 index 00000000000000..84e63184c675d7 --- /dev/null +++ b/tools/gyp/test/ninja/use-console/use-console.gyp @@ -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 --git a/tools/gyp/test/ninja/use-custom-environment-files/gyptest-use-custom-environment-files.py b/tools/gyp/test/ninja/use-custom-environment-files/gyptest-use-custom-environment-files.py new file mode 100644 index 00000000000000..0c44b1d1c98704 --- /dev/null +++ b/tools/gyp/test/ninja/use-custom-environment-files/gyptest-use-custom-environment-files.py @@ -0,0 +1,28 @@ +#!/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. + +""" +Make sure environment files can be suppressed. +""" + +import TestGyp + +import os +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['ninja']) + + test.run_gyp('use-custom-environment-files.gyp', + '-G', 'ninja_use_custom_environment_files') + + # Make sure environment files do not exist. + if os.path.exists(test.built_file_path('environment.x86')): + test.fail_test() + if os.path.exists(test.built_file_path('environment.x64')): + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/ninja/use-custom-environment-files/use-custom-environment-files.cc b/tools/gyp/test/ninja/use-custom-environment-files/use-custom-environment-files.cc new file mode 100644 index 00000000000000..1711567ef56670 --- /dev/null +++ b/tools/gyp/test/ninja/use-custom-environment-files/use-custom-environment-files.cc @@ -0,0 +1,7 @@ +// 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. + +int main() { + return 0; +} diff --git a/tools/gyp/test/ninja/use-custom-environment-files/use-custom-environment-files.gyp b/tools/gyp/test/ninja/use-custom-environment-files/use-custom-environment-files.gyp new file mode 100644 index 00000000000000..dbc95a9439c28b --- /dev/null +++ b/tools/gyp/test/ninja/use-custom-environment-files/use-custom-environment-files.gyp @@ -0,0 +1,15 @@ +# Copyright (c) 2010 Google 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_use_custom_environment_files', + 'type': 'executable', + 'sources': [ + 'use-custom-environment-files.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/no-cpp/gyptest-no-cpp.py b/tools/gyp/test/no-cpp/gyptest-no-cpp.py new file mode 100644 index 00000000000000..a5d64512afffea --- /dev/null +++ b/tools/gyp/test/no-cpp/gyptest-no-cpp.py @@ -0,0 +1,53 @@ +#!/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 C-only targets aren't linked against libstdc++. +""" + +import TestGyp + +import re +import subprocess +import sys + +# set |match| to ignore build stderr output. +test = TestGyp.TestGyp(match = lambda a, b: True) +if (sys.platform != 'win32' and + not (sys.platform == 'darwin' and test.format == 'make')): + # TODO: Does a test like this make sense with Windows? + + CHDIR = 'src' + test.run_gyp('test.gyp', chdir=CHDIR) + test.build('test.gyp', 'no_cpp', chdir=CHDIR) + + def LinksLibStdCpp(path): + path = test.built_file_path(path, chdir=CHDIR) + if sys.platform == 'darwin': + proc = subprocess.Popen(['otool', '-L', path], stdout=subprocess.PIPE) + else: + proc = subprocess.Popen(['ldd', path], stdout=subprocess.PIPE) + output = proc.communicate()[0].decode('utf-8') + assert not proc.returncode + return 'libstdc++' in output or 'libc++' in output + + if LinksLibStdCpp('no_cpp'): + test.fail_test() + + # Make, ninja, and CMake pick the compiler driver based on transitive + # checks. Xcode doesn't. + build_error_code = { + 'xcode': 65, # EX_DATAERR, see `man sysexits` + 'make': 0, + 'ninja': 0, + 'cmake': 0, + 'xcode-ninja': 0, + }[test.format] + + test.build('test.gyp', 'no_cpp_dep_on_cc_lib', chdir=CHDIR, + status=build_error_code) + + test.pass_test() diff --git a/tools/gyp/test/no-cpp/src/call-f-main.c b/tools/gyp/test/no-cpp/src/call-f-main.c new file mode 100644 index 00000000000000..8b95c5910ecc9a --- /dev/null +++ b/tools/gyp/test/no-cpp/src/call-f-main.c @@ -0,0 +1,2 @@ +void* f(); +int main() { f(); } diff --git a/tools/gyp/test/no-cpp/src/empty-main.c b/tools/gyp/test/no-cpp/src/empty-main.c new file mode 100644 index 00000000000000..237c8ce181774d --- /dev/null +++ b/tools/gyp/test/no-cpp/src/empty-main.c @@ -0,0 +1 @@ +int main() {} diff --git a/tools/gyp/test/no-cpp/src/f.cc b/tools/gyp/test/no-cpp/src/f.cc new file mode 100644 index 00000000000000..02f50f21a0ae32 --- /dev/null +++ b/tools/gyp/test/no-cpp/src/f.cc @@ -0,0 +1,3 @@ +extern "C" { void* f(); } + +void* f() { return new int; } diff --git a/tools/gyp/test/no-cpp/src/test.gyp b/tools/gyp/test/no-cpp/src/test.gyp new file mode 100644 index 00000000000000..417015ec803225 --- /dev/null +++ b/tools/gyp/test/no-cpp/src/test.gyp @@ -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. +{ + 'targets': [ + { + 'target_name': 'no_cpp', + 'type': 'executable', + 'sources': [ 'empty-main.c' ], + }, + # A static_library with a cpp file and a linkable with only .c files + # depending on it causes a linker error: + { + 'target_name': 'cpp_lib', + 'type': 'static_library', + 'sources': [ 'f.cc' ], + }, + { + 'target_name': 'no_cpp_dep_on_cc_lib', + 'type': 'executable', + 'dependencies': [ 'cpp_lib' ], + 'sources': [ 'call-f-main.c' ], + }, + ], +} diff --git a/tools/gyp/test/no-output/gyptest-no-output.py b/tools/gyp/test/no-output/gyptest-no-output.py new file mode 100644 index 00000000000000..bf9a0b5aaa4c24 --- /dev/null +++ b/tools/gyp/test/no-output/gyptest-no-output.py @@ -0,0 +1,21 @@ +#!/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. + +""" +Verified things don't explode when there are targets without outputs. +""" + +import TestGyp + +# TODO(evan): in ninja when there are no targets, there is no 'all' +# target either. Disabling this test for now. +test = TestGyp.TestGyp(formats=['!ninja']) + +test.run_gyp('nooutput.gyp', chdir='src') +test.relocate('src', 'relocate/src') +test.build('nooutput.gyp', chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/no-output/src/nooutput.gyp b/tools/gyp/test/no-output/src/nooutput.gyp new file mode 100644 index 00000000000000..c40124efc1eee9 --- /dev/null +++ b/tools/gyp/test/no-output/src/nooutput.gyp @@ -0,0 +1,17 @@ +# 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': 'no_output', + 'type': 'none', + 'direct_dependent_settings': { + 'defines': [ + 'NADA', + ], + }, + }, + ], +} diff --git a/tools/gyp/test/product/gyptest-product.py b/tools/gyp/test/product/gyptest-product.py new file mode 100644 index 00000000000000..53eb5c376b61c3 --- /dev/null +++ b/tools/gyp/test/product/gyptest-product.py @@ -0,0 +1,43 @@ +#!/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 simplest-possible build of a "Hello, world!" program +using the default build target. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('product.gyp') +test.build('product.gyp') + +# executables +test.built_file_must_exist('alt1' + test._exe, test.EXECUTABLE, bare=True) +test.built_file_must_exist('hello2.stuff', test.EXECUTABLE, bare=True) +test.built_file_must_exist('yoalt3.stuff', test.EXECUTABLE, bare=True) + +# shared libraries +test.built_file_must_exist(test.dll_ + 'alt4' + test._dll, + test.SHARED_LIB, bare=True) +test.built_file_must_exist(test.dll_ + 'hello5.stuff', + test.SHARED_LIB, bare=True) +test.built_file_must_exist('yoalt6.stuff', test.SHARED_LIB, bare=True) + +# static libraries +test.built_file_must_exist(test.lib_ + 'alt7' + test._lib, + test.STATIC_LIB, bare=True) +test.built_file_must_exist(test.lib_ + 'hello8.stuff', + test.STATIC_LIB, bare=True) +test.built_file_must_exist('yoalt9.stuff', test.STATIC_LIB, bare=True) + +# alternate product_dir +test.built_file_must_exist('bob/yoalt10.stuff', test.EXECUTABLE, bare=True) +test.built_file_must_exist('bob/yoalt11.stuff', test.EXECUTABLE, bare=True) +test.built_file_must_exist('bob/yoalt12.stuff', test.EXECUTABLE, bare=True) + +test.pass_test() diff --git a/tools/gyp/test/product/hello.c b/tools/gyp/test/product/hello.c new file mode 100644 index 00000000000000..41fdff0e382361 --- /dev/null +++ b/tools/gyp/test/product/hello.c @@ -0,0 +1,15 @@ +/* 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. */ + +#include + +int func1(void) { + return 42; +} + +int main(void) { + printf("Hello, world!\n"); + printf("%d\n", func1()); + return 0; +} diff --git a/tools/gyp/test/product/product.gyp b/tools/gyp/test/product/product.gyp new file mode 100644 index 00000000000000..c25eaaacb51b51 --- /dev/null +++ b/tools/gyp/test/product/product.gyp @@ -0,0 +1,128 @@ +# 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_name': 'alt1', + 'type': 'executable', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello2', + 'product_extension': 'stuff', + 'type': 'executable', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello3', + 'product_name': 'alt3', + 'product_extension': 'stuff', + 'product_prefix': 'yo', + 'type': 'executable', + 'sources': [ + 'hello.c', + ], + }, + + { + 'target_name': 'hello4', + 'product_name': 'alt4', + 'type': 'shared_library', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello5', + 'product_extension': 'stuff', + 'type': 'shared_library', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello6', + 'product_name': 'alt6', + 'product_extension': 'stuff', + 'product_prefix': 'yo', + 'type': 'shared_library', + 'sources': [ + 'hello.c', + ], + }, + + { + 'target_name': 'hello7', + 'product_name': 'alt7', + 'type': 'static_library', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello8', + 'product_extension': 'stuff', + 'type': 'static_library', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello9', + 'product_name': 'alt9', + 'product_extension': 'stuff', + 'product_prefix': 'yo', + 'type': 'static_library', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello10', + 'product_name': 'alt10', + 'product_extension': 'stuff', + 'product_prefix': 'yo', + 'product_dir': '<(PRODUCT_DIR)/bob', + 'type': 'executable', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello11', + 'product_name': 'alt11', + 'product_extension': 'stuff', + 'product_prefix': 'yo', + 'product_dir': '<(PRODUCT_DIR)/bob', + 'type': 'shared_library', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello12', + 'product_name': 'alt12', + 'product_extension': 'stuff', + 'product_prefix': 'yo', + 'product_dir': '<(PRODUCT_DIR)/bob', + 'type': 'static_library', + 'sources': [ + 'hello.c', + ], + }, + ], + 'conditions': [ + ['OS=="linux"', { + 'target_defaults': { + 'cflags': ['-fPIC'], + }, + }], + ], +} diff --git a/tools/gyp/test/prune_targets/gyptest-prune-targets.py b/tools/gyp/test/prune_targets/gyptest-prune-targets.py new file mode 100644 index 00000000000000..401a1af25b80e1 --- /dev/null +++ b/tools/gyp/test/prune_targets/gyptest-prune-targets.py @@ -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 in ['xcode-ninja', 'make-mock']: + test.skip_test() + +build_error_code = { + 'cmake': 1, + 'make': 2, + 'msvs': 1, + 'ninja': 1, + 'xcode': 65, +}.get(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 --git a/tools/gyp/test/prune_targets/lib1.cc b/tools/gyp/test/prune_targets/lib1.cc new file mode 100644 index 00000000000000..692b7de6d82c92 --- /dev/null +++ b/tools/gyp/test/prune_targets/lib1.cc @@ -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 --git a/tools/gyp/test/prune_targets/lib2.cc b/tools/gyp/test/prune_targets/lib2.cc new file mode 100644 index 00000000000000..aed394afcff768 --- /dev/null +++ b/tools/gyp/test/prune_targets/lib2.cc @@ -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 --git a/tools/gyp/test/prune_targets/lib3.cc b/tools/gyp/test/prune_targets/lib3.cc new file mode 100644 index 00000000000000..af0f717b020e5b --- /dev/null +++ b/tools/gyp/test/prune_targets/lib3.cc @@ -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 --git a/tools/gyp/test/prune_targets/lib_indirect.cc b/tools/gyp/test/prune_targets/lib_indirect.cc new file mode 100644 index 00000000000000..92d9ea40db811b --- /dev/null +++ b/tools/gyp/test/prune_targets/lib_indirect.cc @@ -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 --git a/tools/gyp/test/prune_targets/program.cc b/tools/gyp/test/prune_targets/program.cc new file mode 100644 index 00000000000000..c9ac070ecd97bb --- /dev/null +++ b/tools/gyp/test/prune_targets/program.cc @@ -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 --git a/tools/gyp/test/prune_targets/test1.gyp b/tools/gyp/test/prune_targets/test1.gyp new file mode 100644 index 00000000000000..b65ec19fa4c02d --- /dev/null +++ b/tools/gyp/test/prune_targets/test1.gyp @@ -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 --git a/tools/gyp/test/prune_targets/test2.gyp b/tools/gyp/test/prune_targets/test2.gyp new file mode 100644 index 00000000000000..16f0fd3290de9c --- /dev/null +++ b/tools/gyp/test/prune_targets/test2.gyp @@ -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 --git a/tools/gyp/test/relative/foo/a/a.cc b/tools/gyp/test/relative/foo/a/a.cc new file mode 100644 index 00000000000000..7d1c9534485659 --- /dev/null +++ b/tools/gyp/test/relative/foo/a/a.cc @@ -0,0 +1,9 @@ +/* + * 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. + */ + +int main() { + return 0; +} diff --git a/tools/gyp/test/relative/foo/a/a.gyp b/tools/gyp/test/relative/foo/a/a.gyp new file mode 100644 index 00000000000000..66316ac681f809 --- /dev/null +++ b/tools/gyp/test/relative/foo/a/a.gyp @@ -0,0 +1,13 @@ +{ + 'targets': [ + { + 'target_name': 'a', + 'type': 'executable', + 'sources': ['a.cc'], + 'dependencies': [ + '../../foo/b/b.gyp:b', + 'c/c.gyp:c', + ], + }, + ], +} diff --git a/tools/gyp/test/relative/foo/a/c/c.cc b/tools/gyp/test/relative/foo/a/c/c.cc new file mode 100644 index 00000000000000..9d2247168441ec --- /dev/null +++ b/tools/gyp/test/relative/foo/a/c/c.cc @@ -0,0 +1,9 @@ +/* + * 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. + */ + +int func() { + return 0; +} diff --git a/tools/gyp/test/relative/foo/a/c/c.gyp b/tools/gyp/test/relative/foo/a/c/c.gyp new file mode 100644 index 00000000000000..c1f087db9934fe --- /dev/null +++ b/tools/gyp/test/relative/foo/a/c/c.gyp @@ -0,0 +1,12 @@ +{ + 'targets': [ + { + 'target_name': 'c', + 'type': 'static_library', + 'sources': ['c.cc'], + 'dependencies': [ + '../../b/b.gyp:b', + ], + }, + ], +} diff --git a/tools/gyp/test/relative/foo/b/b.cc b/tools/gyp/test/relative/foo/b/b.cc new file mode 100644 index 00000000000000..011d59cebb3236 --- /dev/null +++ b/tools/gyp/test/relative/foo/b/b.cc @@ -0,0 +1,9 @@ +/* + * 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. + */ + +int func2() { + return 0; +} diff --git a/tools/gyp/test/relative/foo/b/b.gyp b/tools/gyp/test/relative/foo/b/b.gyp new file mode 100644 index 00000000000000..0ebe4533d3f3f7 --- /dev/null +++ b/tools/gyp/test/relative/foo/b/b.gyp @@ -0,0 +1,9 @@ +{ + 'targets': [ + { + 'target_name': 'b', + 'type': 'static_library', + 'sources': ['b.cc'], + }, + ], +} diff --git a/tools/gyp/test/relative/gyptest-default.py b/tools/gyp/test/relative/gyptest-default.py new file mode 100644 index 00000000000000..685cdfd75e4643 --- /dev/null +++ b/tools/gyp/test/relative/gyptest-default.py @@ -0,0 +1,25 @@ +#!/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 simplest-possible build of a "Hello, world!" program +using the default build target. +""" + +import TestGyp + +test = TestGyp.TestGyp(workdir='workarea_default', formats=['msvs']) + +# Run from down in foo. +test.run_gyp('a.gyp', chdir='foo/a') +sln = test.workpath('foo/a/a.sln') +sln_data = open(sln, 'rb').read().decode('utf-8', 'ignore') +vcproj = sln_data.count('b.vcproj') +vcxproj = sln_data.count('b.vcxproj') +if (vcproj, vcxproj) not in [(1, 0), (0, 1)]: + test.fail_test() + +test.pass_test() diff --git a/tools/gyp/test/rename/filecase/file.c b/tools/gyp/test/rename/filecase/file.c new file mode 100644 index 00000000000000..76e8197013aabc --- /dev/null +++ b/tools/gyp/test/rename/filecase/file.c @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tools/gyp/test/rename/filecase/test-casesensitive.gyp b/tools/gyp/test/rename/filecase/test-casesensitive.gyp new file mode 100644 index 00000000000000..48eaa6eb679da9 --- /dev/null +++ b/tools/gyp/test/rename/filecase/test-casesensitive.gyp @@ -0,0 +1,15 @@ +# 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': 'filecaserename_sensitive', + 'type': 'executable', + 'sources': [ + 'FiLe.c', + 'fIlE.c', + ], + }, + ], +} diff --git a/tools/gyp/test/rename/filecase/test.gyp b/tools/gyp/test/rename/filecase/test.gyp new file mode 100644 index 00000000000000..eaee9337b6c0a6 --- /dev/null +++ b/tools/gyp/test/rename/filecase/test.gyp @@ -0,0 +1,14 @@ +# 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': 'filecaserename', + 'type': 'executable', + 'sources': [ + 'file.c', + ], + }, + ], +} diff --git a/tools/gyp/test/rename/gyptest-filecase.py b/tools/gyp/test/rename/gyptest-filecase.py new file mode 100644 index 00000000000000..daed5180d3e6fe --- /dev/null +++ b/tools/gyp/test/rename/gyptest-filecase.py @@ -0,0 +1,35 @@ +#!/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 files whose file case changes get rebuilt correctly. +""" + +import os +import TestGyp + +test = TestGyp.TestGyp() +CHDIR = 'filecase' +test.run_gyp('test.gyp', chdir=CHDIR) +test.build('test.gyp', test.ALL, chdir=CHDIR) + +os.rename('filecase/file.c', 'filecase/fIlE.c') +test.write('filecase/test.gyp', + test.read('filecase/test.gyp').replace('file.c', 'fIlE.c')) +test.run_gyp('test.gyp', chdir=CHDIR) +test.build('test.gyp', test.ALL, chdir=CHDIR) + + +# Check that having files that differ just in their case still work on +# case-sensitive file systems. +test.write('filecase/FiLe.c', 'int f(); int main() { return f(); }') +test.write('filecase/fIlE.c', 'int f() { return 42; }') +is_case_sensitive = test.read('filecase/FiLe.c') != test.read('filecase/fIlE.c') +if is_case_sensitive: + test.run_gyp('test-casesensitive.gyp', chdir=CHDIR) + test.build('test-casesensitive.gyp', test.ALL, chdir=CHDIR) + +test.pass_test() diff --git a/tools/gyp/test/restat/gyptest-restat.py b/tools/gyp/test/restat/gyptest-restat.py new file mode 100644 index 00000000000000..87379044dda4a4 --- /dev/null +++ b/tools/gyp/test/restat/gyptest-restat.py @@ -0,0 +1,31 @@ +#!/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 dependent rules are executed iff a dependency action modifies its +outputs. +""" + +import TestGyp +import os + +test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + +test.run_gyp('restat.gyp', chdir='src') + +chdir = 'relocate/src' +test.relocate('src', chdir) + +# Building 'dependent' the first time generates 'side_effect', but building it +# the second time doesn't, because 'create_intermediate' doesn't update its +# output. +test.build('restat.gyp', 'dependent', chdir=chdir) +test.built_file_must_exist('side_effect', chdir=chdir) +os.remove(test.built_file_path('side_effect', chdir=chdir)) +test.build('restat.gyp', 'dependent', chdir=chdir) +test.built_file_must_not_exist('side_effect', chdir=chdir) + +test.pass_test() diff --git a/tools/gyp/test/restat/src/create_intermediate.py b/tools/gyp/test/restat/src/create_intermediate.py new file mode 100644 index 00000000000000..a4d7450371d96f --- /dev/null +++ b/tools/gyp/test/restat/src/create_intermediate.py @@ -0,0 +1,17 @@ +#!/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. + +import os +import sys + +""" +Create argv[1] iff it doesn't already exist. +""" + +outfile = sys.argv[1] +if os.path.exists(outfile): + sys.exit() +open(outfile, "wb").close() diff --git a/tools/gyp/test/restat/src/restat.gyp b/tools/gyp/test/restat/src/restat.gyp new file mode 100644 index 00000000000000..ff020e0ce667b5 --- /dev/null +++ b/tools/gyp/test/restat/src/restat.gyp @@ -0,0 +1,50 @@ +# 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': 'create_intermediate', + 'type': 'none', + 'msvs_cygwin_shell': '0', + 'actions': [ + { + 'action_name': 'create_intermediate', + 'inputs': [ + 'create_intermediate.py', + ], + 'outputs': [ + '<(PRODUCT_DIR)/intermediate', + 'ALWAYS.run.ALWAYS', + ], + 'action': [ + 'python', 'create_intermediate.py', '<(PRODUCT_DIR)/intermediate', + ], + }, + ], + }, + { + 'target_name': 'dependent', + 'type': 'none', + 'msvs_cygwin_shell': '0', + 'dependencies': [ + 'create_intermediate', + ], + 'actions': [ + { + 'action_name': 'dependent', + 'inputs': [ + '<(PRODUCT_DIR)/intermediate', + ], + 'outputs': [ + '<(PRODUCT_DIR)/dependent' + ], + 'action': [ + 'python', 'touch.py', '<(PRODUCT_DIR)/dependent', '<(PRODUCT_DIR)/side_effect', + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/restat/src/touch.py b/tools/gyp/test/restat/src/touch.py new file mode 100644 index 00000000000000..7cd781a90ce67b --- /dev/null +++ b/tools/gyp/test/restat/src/touch.py @@ -0,0 +1,16 @@ +#!/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. + +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 --git a/tools/gyp/test/rules/dirname/gyptest-dirname.py b/tools/gyp/test/rules/dirname/gyptest-dirname.py new file mode 100644 index 00000000000000..da5429cbad4e30 --- /dev/null +++ b/tools/gyp/test/rules/dirname/gyptest-dirname.py @@ -0,0 +1,57 @@ +#!/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 simple rules when using an explicit build target of 'all'. +""" + +from __future__ import print_function + +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=['make', 'ninja', 'xcode', 'msvs']) + +test.run_gyp('actions.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('actions.gyp', chdir='relocate/src') + +expect = """\ +no dir here +hi c +hello baz +""" +if test.format == 'xcode': + chdir = 'relocate/src/subdir' +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.dirname', + os.path.join('foo', 'bar')) +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 --git a/tools/gyp/test/rules/dirname/src/actions.gyp b/tools/gyp/test/rules/dirname/src/actions.gyp new file mode 100644 index 00000000000000..c5693c6c9e15cc --- /dev/null +++ b/tools/gyp/test/rules/dirname/src/actions.gyp @@ -0,0 +1,15 @@ +# 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': 'pull_in_all_actions', + 'type': 'none', + 'dependencies': [ + 'subdir/input-rule-dirname.gyp:*', + ], + }, + ], +} diff --git a/tools/gyp/test/rules/dirname/src/copy-file.py b/tools/gyp/test/rules/dirname/src/copy-file.py new file mode 100644 index 00000000000000..271a72b6b1a32c --- /dev/null +++ b/tools/gyp/test/rules/dirname/src/copy-file.py @@ -0,0 +1,11 @@ +#!/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. +import sys + +contents = open(sys.argv[1], 'r').read() +open(sys.argv[2], 'w').write(contents) + +sys.exit(0) diff --git a/tools/gyp/test/rules/dirname/src/subdir/a/b/c.gencc b/tools/gyp/test/rules/dirname/src/subdir/a/b/c.gencc new file mode 100644 index 00000000000000..29cb5f79ad7942 --- /dev/null +++ b/tools/gyp/test/rules/dirname/src/subdir/a/b/c.gencc @@ -0,0 +1,8 @@ +// -*- mode: c++ -*- +#include + +namespace gen { + void c() { + printf("hi c\n"); + } +} diff --git a/tools/gyp/test/rules/dirname/src/subdir/a/b/c.printvars b/tools/gyp/test/rules/dirname/src/subdir/a/b/c.printvars new file mode 100644 index 00000000000000..cc4561dc41426a --- /dev/null +++ b/tools/gyp/test/rules/dirname/src/subdir/a/b/c.printvars @@ -0,0 +1 @@ +# Empty file for testing build rules diff --git a/tools/gyp/test/rules/dirname/src/subdir/foo/bar/baz.gencc b/tools/gyp/test/rules/dirname/src/subdir/foo/bar/baz.gencc new file mode 100644 index 00000000000000..90b4ce9243c527 --- /dev/null +++ b/tools/gyp/test/rules/dirname/src/subdir/foo/bar/baz.gencc @@ -0,0 +1,8 @@ +// -*- mode: c++ -*- +#include + +namespace gen { + void baz() { + printf("hello baz\n"); + } +} diff --git a/tools/gyp/test/rules/dirname/src/subdir/foo/bar/baz.printvars b/tools/gyp/test/rules/dirname/src/subdir/foo/bar/baz.printvars new file mode 100644 index 00000000000000..cc4561dc41426a --- /dev/null +++ b/tools/gyp/test/rules/dirname/src/subdir/foo/bar/baz.printvars @@ -0,0 +1 @@ +# Empty file for testing build rules diff --git a/tools/gyp/test/rules/dirname/src/subdir/input-rule-dirname.gyp b/tools/gyp/test/rules/dirname/src/subdir/input-rule-dirname.gyp new file mode 100644 index 00000000000000..da749a2231fe11 --- /dev/null +++ b/tools/gyp/test/rules/dirname/src/subdir/input-rule-dirname.gyp @@ -0,0 +1,140 @@ +# 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': 'print_rule_input_dirname', + '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).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, + 'sources': [ + 'nodir.gencc', + 'foo/bar/baz.gencc', + 'a/b/c.gencc', + 'main.cc', + ], + 'rules': [ + { + 'rule_name': 'gencc', + 'extension': 'gencc', + '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, + }, + ], + }, + ], + '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': [ + { + 'action_name': 'setup_mount', + 'msvs_cygwin_shell': 0, + 'inputs': [ + '../../../../../../<(DEPTH)/third_party/cygwin/setup_mount.bat', + ], + # Visual Studio requires an output file, or else the + # custom build step won't run. + 'outputs': [ + '<(INTERMEDIATE_DIR)/_always_run_setup_mount.marker', + ], + 'action': ['<@(_inputs)'], + }, + ], + }, + ], + }], + ], +} diff --git a/tools/gyp/test/rules/dirname/src/subdir/main.cc b/tools/gyp/test/rules/dirname/src/subdir/main.cc new file mode 100644 index 00000000000000..3bb8e01395ee83 --- /dev/null +++ b/tools/gyp/test/rules/dirname/src/subdir/main.cc @@ -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. +namespace gen { + extern void nodir(); + extern void c(); + extern void baz(); +} + +int main() { + gen::nodir(); + gen::c(); + gen::baz(); +} diff --git a/tools/gyp/test/rules/dirname/src/subdir/nodir.gencc b/tools/gyp/test/rules/dirname/src/subdir/nodir.gencc new file mode 100644 index 00000000000000..720f589bc2cb8c --- /dev/null +++ b/tools/gyp/test/rules/dirname/src/subdir/nodir.gencc @@ -0,0 +1,8 @@ +// -*- mode: c++ -*- +#include + +namespace gen { + void nodir() { + printf("no dir here\n"); + } +} diff --git a/tools/gyp/test/rules/dirname/src/subdir/printvars.py b/tools/gyp/test/rules/dirname/src/subdir/printvars.py new file mode 100644 index 00000000000000..ef3d92e8cf7ec8 --- /dev/null +++ b/tools/gyp/test/rules/dirname/src/subdir/printvars.py @@ -0,0 +1,14 @@ +#!/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. + +""" +Prints interesting vars +""" + +import sys; + +out = open(sys.argv[2], 'w') +out.write(sys.argv[1]); diff --git a/tools/gyp/test/rules/e2e/gyptest-all.py b/tools/gyp/test/rules/e2e/gyptest-all.py new file mode 100644 index 00000000000000..0520c2f6a03489 --- /dev/null +++ b/tools/gyp/test/rules/e2e/gyptest-all.py @@ -0,0 +1,84 @@ +#!/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 simple rules when using an explicit build target of 'all'. +""" + +from __future__ import print_function + +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('no_action_with_rules_fails.gyp', chdir='src/noaction', status=1, + stderr=None) + +test.run_gyp('actions.gyp', + '-G', 'xcode_ninja_target_pattern=^pull_in_all_actions$', + chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('actions.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from program.c +Hello from function1.in +Hello from function2.in +""" + +if test.format == 'xcode': + chdir = 'relocate/src/subdir1' +else: + chdir = 'relocate/src' +test.run_built_executable('program', chdir=chdir, stdout=expect) + +expect = """\ +Hello from program.c +Hello from function3.in +""" + +if test.format == 'xcode': + chdir = 'relocate/src/subdir3' +else: + chdir = 'relocate/src' +test.run_built_executable('program2', chdir=chdir, stdout=expect) + +test.must_match('relocate/src/subdir2/file1.out', 'Hello from file1.in\n') +test.must_match('relocate/src/subdir2/file2.out', 'Hello from file2.in\n') + +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', + 'Hello from file2.in\n') + +expect = """\ +Hello from program.c +Got 41. +""" + +if test.format == 'xcode': + chdir = 'relocate/src/subdir4' +else: + chdir = 'relocate/src' +test.run_built_executable('program4', chdir=chdir, stdout=expect) + +test.pass_test() diff --git a/tools/gyp/test/rules/e2e/gyptest-default.py b/tools/gyp/test/rules/e2e/gyptest-default.py new file mode 100644 index 00000000000000..5d01094197bb1e --- /dev/null +++ b/tools/gyp/test/rules/e2e/gyptest-default.py @@ -0,0 +1,70 @@ +#!/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 simple rules when using an explicit build target of 'all'. +""" + +from __future__ import print_function + +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', + '-G', 'xcode_ninja_target_pattern=^pull_in_all_actions$', + chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('actions.gyp', chdir='relocate/src') + +expect = """\ +Hello from program.c +Hello from function1.in +Hello from function2.in +""" + +if test.format == 'xcode': + chdir = 'relocate/src/subdir1' +else: + chdir = 'relocate/src' +test.run_built_executable('program', chdir=chdir, stdout=expect) + +expect = """\ +Hello from program.c +Hello from function3.in +""" + +if test.format == 'xcode': + chdir = 'relocate/src/subdir3' +else: + chdir = 'relocate/src' +test.run_built_executable('program2', chdir=chdir, stdout=expect) + +test.must_match('relocate/src/subdir2/file1.out', 'Hello from file1.in\n') +test.must_match('relocate/src/subdir2/file2.out', 'Hello from file2.in\n') + +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', + 'Hello from file2.in\n') + +test.pass_test() diff --git a/tools/gyp/test/rules/e2e/gyptest-input-root.py b/tools/gyp/test/rules/e2e/gyptest-input-root.py new file mode 100644 index 00000000000000..92bade6d48be01 --- /dev/null +++ b/tools/gyp/test/rules/e2e/gyptest-input-root.py @@ -0,0 +1,26 @@ +#!/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 RULE_INPUT_ROOT isn't turned into a path in rule actions +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('input-root.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('input-root.gyp', target='test', chdir='relocate/src') + +expect = """\ +Hello somefile +""" + +test.run_built_executable('test', chdir='relocate/src', stdout=expect) +test.pass_test() diff --git a/tools/gyp/test/rules/e2e/gyptest-special-variables.py b/tools/gyp/test/rules/e2e/gyptest-special-variables.py new file mode 100644 index 00000000000000..05ea7cee16e323 --- /dev/null +++ b/tools/gyp/test/rules/e2e/gyptest-special-variables.py @@ -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. + +""" Verifies that VS variables that require special variables are expanded +correctly. """ + +import sys +import TestGyp + +if sys.platform == 'win32': + test = TestGyp.TestGyp() + + test.run_gyp('special-variables.gyp', chdir='src') + test.build('special-variables.gyp', test.ALL, chdir='src') + test.pass_test() diff --git a/tools/gyp/test/rules/e2e/src/actions.gyp b/tools/gyp/test/rules/e2e/src/actions.gyp new file mode 100644 index 00000000000000..84376a71937803 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/actions.gyp @@ -0,0 +1,23 @@ +# 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': 'pull_in_all_actions', + '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:*', + 'subdir2/none.gyp:*', + 'subdir3/executable2.gyp:*', + 'subdir4/build-asm.gyp:*', + 'external/external.gyp:*', + ], + }, + ], +} diff --git a/tools/gyp/test/rules/e2e/src/an_asm.S b/tools/gyp/test/rules/e2e/src/an_asm.S new file mode 100644 index 00000000000000..eeb13455500135 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/an_asm.S @@ -0,0 +1,6 @@ +// 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. + +// Fake asm file. +int main() {} diff --git a/tools/gyp/test/rules/e2e/src/as.bat b/tools/gyp/test/rules/e2e/src/as.bat new file mode 100644 index 00000000000000..04636c5166d84f --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/as.bat @@ -0,0 +1,7 @@ +@echo off +:: 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. + +:: Fake assembler for Windows +cl /TP /c %1 /Fo%2 diff --git a/tools/gyp/test/rules/e2e/src/copy-file.py b/tools/gyp/test/rules/e2e/src/copy-file.py new file mode 100644 index 00000000000000..7bdfbfd4bd65bd --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/copy-file.py @@ -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], 'w').write(contents) + +sys.exit(0) diff --git a/tools/gyp/test/rules/e2e/src/external/external.gyp b/tools/gyp/test/rules/e2e/src/external/external.gyp new file mode 100644 index 00000000000000..b28174f57c3c91 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/external/external.gyp @@ -0,0 +1,66 @@ +# 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. + +# Test that the case where there are no inputs (other than the +# file the rule applies to). +{ + 'target_defaults': { + 'msvs_cygwin_dirs': ['../../../../../../<(DEPTH)/third_party/cygwin'], + }, + 'targets': [ + { + 'target_name': 'external_rules', + 'type': 'none', + 'sources': [ + 'file1.in', + 'file2.in', + ], + 'conditions': [ + ['OS=="win"', { + 'dependencies': [ + 'cygwin', + ], + }], + ], + 'rules': [ + { + 'rule_name': 'copy_file', + 'extension': 'in', + 'msvs_external_rule': 1, + 'outputs': [ + '<(RULE_INPUT_ROOT).external_rules.out', + ], + 'action': [ + 'python', '../copy-file.py', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + }, + ], + }, + ], + 'conditions': [ + ['OS=="win"', { + 'targets': [ + { + 'target_name': 'cygwin', + 'type': 'none', + 'actions': [ + { + 'action_name': 'setup_mount', + 'msvs_cygwin_shell': 0, + 'inputs': [ + '../../../../../../<(DEPTH)/third_party/cygwin/setup_mount.bat', + ], + # Visual Studio requires an output file, or else the + # custom build step won't run. + 'outputs': [ + '<(INTERMEDIATE_DIR)/_always_run_setup_mount.marker', + ], + 'action': ['<@(_inputs)'], + }, + ], + }, + ], + }], + ], +} diff --git a/tools/gyp/test/rules/e2e/src/external/file1.in b/tools/gyp/test/rules/e2e/src/external/file1.in new file mode 100644 index 00000000000000..86ac3ad389d0f3 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/external/file1.in @@ -0,0 +1 @@ +Hello from file1.in diff --git a/tools/gyp/test/rules/e2e/src/external/file2.in b/tools/gyp/test/rules/e2e/src/external/file2.in new file mode 100644 index 00000000000000..bf83d8ecece575 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/external/file2.in @@ -0,0 +1 @@ +Hello from file2.in diff --git a/tools/gyp/test/rules/e2e/src/input-root.gyp b/tools/gyp/test/rules/e2e/src/input-root.gyp new file mode 100644 index 00000000000000..b6600e767c8ead --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/input-root.gyp @@ -0,0 +1,24 @@ +# 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': 'test', + 'type': 'executable', + 'sources': [ 'somefile.ext', ], + 'rules': [{ + 'rule_name': 'rule', + 'extension': 'ext', + 'inputs': [ 'rule.py', ], + 'outputs': [ '<(RULE_INPUT_ROOT).cc', ], + 'action': [ 'python', 'rule.py', '<(RULE_INPUT_ROOT)', ], + 'message': 'Processing <(RULE_INPUT_PATH)', + 'process_outputs_as_sources': 1, + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }], + }, + ], +} diff --git a/tools/gyp/test/rules/e2e/src/noaction/file1.in b/tools/gyp/test/rules/e2e/src/noaction/file1.in new file mode 100644 index 00000000000000..86ac3ad389d0f3 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/noaction/file1.in @@ -0,0 +1 @@ +Hello from file1.in diff --git a/tools/gyp/test/rules/e2e/src/noaction/no_action_with_rules_fails.gyp b/tools/gyp/test/rules/e2e/src/noaction/no_action_with_rules_fails.gyp new file mode 100644 index 00000000000000..9b6a65629f3b86 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/noaction/no_action_with_rules_fails.gyp @@ -0,0 +1,37 @@ +# 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. + +# Test the case where there's no action but there are input rules that should +# be processed results in a gyp failure. +{ + 'targets': [ + { + 'target_name': 'extension_does_match_sources_but_no_action', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'file1.in', + ], + 'rules': [ + { + 'rule_name': 'assembled', + 'extension': 'in', + 'outputs': [ + '<(RULE_INPUT_ROOT).in', + ], + 'conditions': [ + # Always fails. + [ '"true"=="false"', { + 'action': [ + 'python', '../copy-file.py', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + 'message': 'test_rule', + }], + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/rules/e2e/src/rule.py b/tools/gyp/test/rules/e2e/src/rule.py new file mode 100644 index 00000000000000..8a1f36dedb1811 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/rule.py @@ -0,0 +1,17 @@ +#!/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. + +import sys + +f = open(sys.argv[1] + ".cc", "w") +f.write("""\ +#include + +int main() { + puts("Hello %s"); + return 0; +} +""" % sys.argv[1]) +f.close() diff --git a/tools/gyp/test/rules/e2e/src/somefile.ext b/tools/gyp/test/rules/e2e/src/somefile.ext new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/rules/e2e/src/special-variables.gyp b/tools/gyp/test/rules/e2e/src/special-variables.gyp new file mode 100644 index 00000000000000..d1443af5ba0fd4 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/special-variables.gyp @@ -0,0 +1,34 @@ +# 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': [ + { + 'rules': [ + { + 'rule_name': 'assembler (gnu-compatible)', + 'msvs_cygwin_shell': 0, + 'msvs_quote_cmd': 0, + 'extension': 'S', + 'inputs': [ + 'as.bat', + ], + 'outputs': [ + '$(IntDir)/$(InputName).obj', + ], + 'action': [ + 'as.bat', + '$(InputPath)', + '$(IntDir)/$(InputName).obj', + ], + 'message': 'Building assembly language file $(InputPath)', + 'process_outputs_as_sources': 1, + }, + ], + 'target_name': 'test', + 'type': 'static_library', + 'sources': [ 'an_asm.S' ], + }, + ], +} diff --git a/tools/gyp/test/rules/e2e/src/subdir1/executable.gyp b/tools/gyp/test/rules/e2e/src/subdir1/executable.gyp new file mode 100644 index 00000000000000..c34cce5a92e23e --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir1/executable.gyp @@ -0,0 +1,37 @@ +# 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': 'program', + 'type': 'executable', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'program.c', + 'function1.in', + 'function2.in', + ], + 'rules': [ + { + 'rule_name': 'copy_file', + 'extension': 'in', + 'inputs': [ + '../copy-file.py', + ], + 'outputs': [ + # TODO: fix Make to support generated files not + # in a variable-named path like <(INTERMEDIATE_DIR) + #'<(RULE_INPUT_ROOT).c', + '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).c', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/rules/e2e/src/subdir1/function1.in b/tools/gyp/test/rules/e2e/src/subdir1/function1.in new file mode 100644 index 00000000000000..60ff28949b9af5 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir1/function1.in @@ -0,0 +1,6 @@ +#include + +void function1(void) +{ + printf("Hello from function1.in\n"); +} diff --git a/tools/gyp/test/rules/e2e/src/subdir1/function2.in b/tools/gyp/test/rules/e2e/src/subdir1/function2.in new file mode 100644 index 00000000000000..0fcfc03fdb91ea --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir1/function2.in @@ -0,0 +1,6 @@ +#include + +void function2(void) +{ + printf("Hello from function2.in\n"); +} diff --git a/tools/gyp/test/rules/e2e/src/subdir1/program.c b/tools/gyp/test/rules/e2e/src/subdir1/program.c new file mode 100644 index 00000000000000..6b11ff9f6753ce --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir1/program.c @@ -0,0 +1,12 @@ +#include + +extern void function1(void); +extern void function2(void); + +int main(void) +{ + printf("Hello from program.c\n"); + function1(); + function2(); + return 0; +} diff --git a/tools/gyp/test/rules/e2e/src/subdir2/both_rule_and_action_input.gyp b/tools/gyp/test/rules/e2e/src/subdir2/both_rule_and_action_input.gyp new file mode 100644 index 00000000000000..e5e6f3ec2b19ec --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir2/both_rule_and_action_input.gyp @@ -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 --git a/tools/gyp/test/rules/e2e/src/subdir2/file1.in b/tools/gyp/test/rules/e2e/src/subdir2/file1.in new file mode 100644 index 00000000000000..86ac3ad389d0f3 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir2/file1.in @@ -0,0 +1 @@ +Hello from file1.in diff --git a/tools/gyp/test/rules/e2e/src/subdir2/file2.in b/tools/gyp/test/rules/e2e/src/subdir2/file2.in new file mode 100644 index 00000000000000..bf83d8ecece575 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir2/file2.in @@ -0,0 +1 @@ +Hello from file2.in diff --git a/tools/gyp/test/rules/e2e/src/subdir2/never_used.gyp b/tools/gyp/test/rules/e2e/src/subdir2/never_used.gyp new file mode 100644 index 00000000000000..17f6f553710cdd --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir2/never_used.gyp @@ -0,0 +1,31 @@ +# 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. + +# Test that the case where there is a rule that doesn't apply to anything. +{ + 'targets': [ + { + 'target_name': 'files_no_input2', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'file1.in', + 'file2.in', + ], + 'rules': [ + { + 'rule_name': 'copy_file3', + 'extension': 'in2', + 'outputs': [ + '<(RULE_INPUT_ROOT).out3', + ], + 'action': [ + 'python', '../copy-file.py', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/rules/e2e/src/subdir2/no_action.gyp b/tools/gyp/test/rules/e2e/src/subdir2/no_action.gyp new file mode 100644 index 00000000000000..ffa1cefe182f95 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir2/no_action.gyp @@ -0,0 +1,38 @@ +# 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. + +# Test that the case where an action is only specified under a conditional is +# evaluated appropriately. +{ + 'targets': [ + { + 'target_name': 'extension_does_not_match_sources_and_no_action', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'file1.in', + 'file2.in', + ], + 'rules': [ + { + 'rule_name': 'assemble', + 'extension': 'asm', + 'outputs': [ + '<(RULE_INPUT_ROOT).fail', + ], + 'conditions': [ + # Always fails. + [ '"true"=="false"', { + 'action': [ + 'python', '../copy-file.py', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + 'message': 'test_rule', + }], + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/rules/e2e/src/subdir2/no_inputs.gyp b/tools/gyp/test/rules/e2e/src/subdir2/no_inputs.gyp new file mode 100644 index 00000000000000..e61a1a3ff674ac --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir2/no_inputs.gyp @@ -0,0 +1,32 @@ +# 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. + +# Test that the case where there are no inputs (other than the +# file the rule applies to). +{ + 'targets': [ + { + 'target_name': 'files_no_input', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'file1.in', + 'file2.in', + ], + 'rules': [ + { + 'rule_name': 'copy_file2', + 'extension': 'in', + 'outputs': [ + '<(RULE_INPUT_ROOT).out2', + ], + 'action': [ + 'python', '../copy-file.py', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/rules/e2e/src/subdir2/none.gyp b/tools/gyp/test/rules/e2e/src/subdir2/none.gyp new file mode 100644 index 00000000000000..38bcdabdf6616e --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir2/none.gyp @@ -0,0 +1,33 @@ +# 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': 'files', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'file1.in', + 'file2.in', + ], + 'rules': [ + { + 'rule_name': 'copy_file', + 'extension': 'in', + 'inputs': [ + '../copy-file.py', + ], + 'outputs': [ + '<(RULE_INPUT_ROOT).out', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/rules/e2e/src/subdir2/program.c b/tools/gyp/test/rules/e2e/src/subdir2/program.c new file mode 100644 index 00000000000000..e5db175148e706 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir2/program.c @@ -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 --git a/tools/gyp/test/rules/e2e/src/subdir3/executable2.gyp b/tools/gyp/test/rules/e2e/src/subdir3/executable2.gyp new file mode 100644 index 00000000000000..a2a528fc7bea18 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir3/executable2.gyp @@ -0,0 +1,37 @@ +# 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. + +# This one tests that rules are properly written if extensions are different +# between the target's sources (program.c) and the generated files +# (function3.cc) + +{ + 'targets': [ + { + 'target_name': 'program2', + 'type': 'executable', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'program.c', + 'function3.in', + ], + 'rules': [ + { + 'rule_name': 'copy_file', + 'extension': 'in', + 'inputs': [ + '../copy-file.py', + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).cc', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/rules/e2e/src/subdir3/function3.in b/tools/gyp/test/rules/e2e/src/subdir3/function3.in new file mode 100644 index 00000000000000..99f46ab05e6ec4 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir3/function3.in @@ -0,0 +1,6 @@ +#include + +extern "C" void function3(void) +{ + printf("Hello from function3.in\n"); +} diff --git a/tools/gyp/test/rules/e2e/src/subdir3/program.c b/tools/gyp/test/rules/e2e/src/subdir3/program.c new file mode 100644 index 00000000000000..c38eead50e89fa --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir3/program.c @@ -0,0 +1,10 @@ +#include + +extern void function3(void); + +int main(void) +{ + printf("Hello from program.c\n"); + function3(); + return 0; +} diff --git a/tools/gyp/test/rules/e2e/src/subdir4/asm-function.assem b/tools/gyp/test/rules/e2e/src/subdir4/asm-function.assem new file mode 100644 index 00000000000000..ed47cade95926f --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir4/asm-function.assem @@ -0,0 +1,10 @@ +#if PLATFORM_WINDOWS || PLATFORM_MAC +# define IDENTIFIER(n) _##n +#else /* Linux */ +# define IDENTIFIER(n) n +#endif + +.globl IDENTIFIER(asm_function) +IDENTIFIER(asm_function): + movl $41, %eax + ret diff --git a/tools/gyp/test/rules/e2e/src/subdir4/build-asm.gyp b/tools/gyp/test/rules/e2e/src/subdir4/build-asm.gyp new file mode 100644 index 00000000000000..fe0fe93787e1e7 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir4/build-asm.gyp @@ -0,0 +1,49 @@ +# 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. + +# This one tests that assembly files ended as .s and .S are compiled. + +{ + 'target_defaults': { + 'conditions': [ + ['OS=="win"', { + 'defines': ['PLATFORM_WIN'], + }], + ['OS=="mac"', { + 'defines': ['PLATFORM_MAC'], + }], + ['OS=="linux"', { + 'defines': ['PLATFORM_LINUX'], + }], + ], + }, + 'targets': [ + { + 'target_name': 'program4', + 'type': 'executable', + 'sources': [ + 'asm-function.assem', + 'program.c', + ], + 'conditions': [ + ['OS=="linux" or OS=="mac"', { + 'rules': [ + { + 'rule_name': 'convert_assem', + 'extension': 'assem', + 'inputs': [], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).S', + ], + 'action': [ + 'bash', '-c', 'cp <(RULE_INPUT_PATH) <@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }], + ], + }, + ], +} diff --git a/tools/gyp/test/rules/e2e/src/subdir4/program.c b/tools/gyp/test/rules/e2e/src/subdir4/program.c new file mode 100644 index 00000000000000..ad647f4eb991b1 --- /dev/null +++ b/tools/gyp/test/rules/e2e/src/subdir4/program.c @@ -0,0 +1,19 @@ +#include + +// Use the assembly function in linux and mac where it is built. +#if PLATFORM_LINUX || PLATFORM_MAC +extern int asm_function(void); +#else +int asm_function() { + return 41; +} +#endif + +int main(void) +{ + fprintf(stdout, "Hello from program.c\n"); + fflush(stdout); + fprintf(stdout, "Got %d.\n", asm_function()); + fflush(stdout); + return 0; +} diff --git a/tools/gyp/test/rules/rebuild/gyptest-all.py b/tools/gyp/test/rules/rebuild/gyptest-all.py new file mode 100644 index 00000000000000..aaaa2a6e6f9084 --- /dev/null +++ b/tools/gyp/test/rules/rebuild/gyptest-all.py @@ -0,0 +1,70 @@ +#!/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 that a rule that generates multiple outputs rebuilds +correctly when the inputs change. +""" + +import TestGyp + +test = TestGyp.TestGyp(workdir='workarea_all') + +test.run_gyp('same_target.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + + +test.build('same_target.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from main.c +Hello from prog1.in! +Hello from prog2.in! +""" + +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + +test.up_to_date('same_target.gyp', 'program', chdir='relocate/src') + + +test.sleep() +contents = test.read(['relocate', 'src', 'prog1.in']) +contents = contents.replace('!', ' AGAIN!') +test.write(['relocate', 'src', 'prog1.in'], contents) + +test.build('same_target.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from main.c +Hello from prog1.in AGAIN! +Hello from prog2.in! +""" + +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + +test.up_to_date('same_target.gyp', 'program', chdir='relocate/src') + + +test.sleep() +contents = test.read(['relocate', 'src', 'prog2.in']) +contents = contents.replace('!', ' AGAIN!') +test.write(['relocate', 'src', 'prog2.in'], contents) + +test.build('same_target.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from main.c +Hello from prog1.in AGAIN! +Hello from prog2.in AGAIN! +""" + +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + +test.up_to_date('same_target.gyp', 'program', chdir='relocate/src') + + +test.pass_test() diff --git a/tools/gyp/test/rules/rebuild/gyptest-default.py b/tools/gyp/test/rules/rebuild/gyptest-default.py new file mode 100644 index 00000000000000..ac3f0209aa0429 --- /dev/null +++ b/tools/gyp/test/rules/rebuild/gyptest-default.py @@ -0,0 +1,91 @@ +#!/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 a rule that generates multiple outputs rebuilds +correctly when the inputs change. +""" + +import TestGyp + +test = TestGyp.TestGyp(workdir='workarea_default') + +test.run_gyp('same_target.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + + +test.build('same_target.gyp', chdir='relocate/src') + +expect = """\ +Hello from main.c +Hello from prog1.in! +Hello from prog2.in! +""" + +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + +test.up_to_date('same_target.gyp', 'program', chdir='relocate/src') + + +test.sleep() +contents = test.read(['relocate', 'src', 'prog1.in']) +contents = contents.replace('!', ' AGAIN!') +test.write(['relocate', 'src', 'prog1.in'], contents) + +test.build('same_target.gyp', chdir='relocate/src') + +expect = """\ +Hello from main.c +Hello from prog1.in AGAIN! +Hello from prog2.in! +""" + +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + +test.up_to_date('same_target.gyp', 'program', chdir='relocate/src') + + +test.sleep() +contents = test.read(['relocate', 'src', 'prog2.in']) +contents = contents.replace('!', ' AGAIN!') +test.write(['relocate', 'src', 'prog2.in'], contents) + +test.build('same_target.gyp', chdir='relocate/src') + +expect = """\ +Hello from main.c +Hello from prog1.in AGAIN! +Hello from prog2.in AGAIN! +""" + +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + +test.up_to_date('same_target.gyp', 'program', chdir='relocate/src') + + +# Test that modifying a rule's inputs (specifically, make-sources.py) causes +# the targets to be built. + +test.sleep() +contents = test.read(['relocate', 'src', 'make-sources.py']) +contents = contents.replace('%s', 'the amazing %s') +test.write(['relocate', 'src', 'make-sources.py'], contents) + +test.build('same_target.gyp', chdir='relocate/src') + +expect = """\ +Hello from main.c +Hello from the amazing prog1.in AGAIN! +Hello from the amazing prog2.in AGAIN! +""" + +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + +test.up_to_date('same_target.gyp', 'program', chdir='relocate/src') + + +test.pass_test() diff --git a/tools/gyp/test/rules/rebuild/src/main.c b/tools/gyp/test/rules/rebuild/src/main.c new file mode 100644 index 00000000000000..bd8fbb20ea313f --- /dev/null +++ b/tools/gyp/test/rules/rebuild/src/main.c @@ -0,0 +1,12 @@ +#include + +extern void prog1(void); +extern void prog2(void); + +int main(void) +{ + printf("Hello from main.c\n"); + prog1(); + prog2(); + return 0; +} diff --git a/tools/gyp/test/rules/rebuild/src/make-sources.py b/tools/gyp/test/rules/rebuild/src/make-sources.py new file mode 100644 index 00000000000000..dd9e52856e3e5e --- /dev/null +++ b/tools/gyp/test/rules/rebuild/src/make-sources.py @@ -0,0 +1,19 @@ +#!/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. + +import sys + +assert len(sys.argv) == 4, sys.argv + +(in_file, c_file, h_file) = sys.argv[1:] + +def write_file(filename, contents): + open(filename, 'w').write(contents) + +write_file(c_file, open(in_file, 'r').read()) + +write_file(h_file, '#define NAME "%s"\n' % in_file) + +sys.exit(0) diff --git a/tools/gyp/test/rules/rebuild/src/prog1.in b/tools/gyp/test/rules/rebuild/src/prog1.in new file mode 100644 index 00000000000000..191b00ef1e6a60 --- /dev/null +++ b/tools/gyp/test/rules/rebuild/src/prog1.in @@ -0,0 +1,7 @@ +#include +#include "prog1.h" + +void prog1(void) +{ + printf("Hello from %s!\n", NAME); +} diff --git a/tools/gyp/test/rules/rebuild/src/prog2.in b/tools/gyp/test/rules/rebuild/src/prog2.in new file mode 100644 index 00000000000000..7bfac5104c9ca2 --- /dev/null +++ b/tools/gyp/test/rules/rebuild/src/prog2.in @@ -0,0 +1,7 @@ +#include +#include "prog2.h" + +void prog2(void) +{ + printf("Hello from %s!\n", NAME); +} diff --git a/tools/gyp/test/rules/rebuild/src/same_target.gyp b/tools/gyp/test/rules/rebuild/src/same_target.gyp new file mode 100644 index 00000000000000..22ba56056d2655 --- /dev/null +++ b/tools/gyp/test/rules/rebuild/src/same_target.gyp @@ -0,0 +1,31 @@ +{ + 'targets': [ + { + 'target_name': 'program', + 'type': 'executable', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'main.c', + 'prog1.in', + 'prog2.in', + ], + 'rules': [ + { + 'rule_name': 'make_sources', + 'extension': 'in', + 'inputs': [ + 'make-sources.py', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).c', + '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).h', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_NAME)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/rules/use-built-dependencies/gyptest-use-built-dependencies.py b/tools/gyp/test/rules/use-built-dependencies/gyptest-use-built-dependencies.py new file mode 100644 index 00000000000000..a57c36d5b0dda4 --- /dev/null +++ b/tools/gyp/test/rules/use-built-dependencies/gyptest-use-built-dependencies.py @@ -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. + +""" +Verifies that rules which use built dependencies work correctly. +""" + +import TestGyp + +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') + +test.built_file_must_exist('main_output', chdir='relocate/src') +test.built_file_must_match('main_output', 'output', chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/rules/use-built-dependencies/src/main.cc b/tools/gyp/test/rules/use-built-dependencies/src/main.cc new file mode 100644 index 00000000000000..937d2845992205 --- /dev/null +++ b/tools/gyp/test/rules/use-built-dependencies/src/main.cc @@ -0,0 +1,17 @@ +// 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 + +int main(int argc, char *argv[]) { + if (argc < 2) { + return 2; + } + FILE* file; + file = fopen(argv[1], "wb"); + const char output[] = "output"; + fwrite(output, 1, sizeof(output) - 1, file); + fclose(file); + return 0; +} + diff --git a/tools/gyp/test/rules/use-built-dependencies/src/use-built-dependencies-rule.gyp b/tools/gyp/test/rules/use-built-dependencies/src/use-built-dependencies-rule.gyp new file mode 100644 index 00000000000000..92bfeda39288f1 --- /dev/null +++ b/tools/gyp/test/rules/use-built-dependencies/src/use-built-dependencies-rule.gyp @@ -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': 'main', + 'toolsets': ['host'], + 'type': 'executable', + 'sources': [ + 'main.cc', + ], + }, + { + 'target_name': 'post', + 'toolsets': ['host'], + 'type': 'none', + 'dependencies': [ + 'main', + ], + 'sources': [ + # As this test is written it could easily be made into an action. + # An acutal use case would have a number of these 'sources'. + '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)main<(EXECUTABLE_SUFFIX)', + ], + 'rules': [ + { + 'rule_name': 'generate_output', + 'extension': '<(EXECUTABLE_SUFFIX)', + 'outputs': [ '<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT)_output', ], + 'msvs_cygwin_shell': 0, + 'action': [ + '<(RULE_INPUT_PATH)', + '<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT)_output', + ], + 'message': 'Generating output for <(RULE_INPUT_ROOT)' + }, + ], + }, + ], +} diff --git a/tools/gyp/test/rules/variables/gyptest-rules-variables.py b/tools/gyp/test/rules/variables/gyptest-rules-variables.py new file mode 100644 index 00000000000000..16afc22ef9b751 --- /dev/null +++ b/tools/gyp/test/rules/variables/gyptest-rules-variables.py @@ -0,0 +1,35 @@ +#!/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 rules related variables are expanded. +""" + +from __future__ import print_function + +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']) + +test.relocate('src', 'relocate/src') + +test.run_gyp('variables.gyp', chdir='relocate/src') + +test.build('variables.gyp', chdir='relocate/src') + +test.run_built_executable('all_rule_variables', + chdir='relocate/src', + stdout="input_root\ninput_dirname\ninput_path\n" + + "input_ext\ninput_name\n") + +test.pass_test() diff --git a/tools/gyp/test/rules/variables/src/input_ext.c b/tools/gyp/test/rules/variables/src/input_ext.c new file mode 100644 index 00000000000000..f41e73ef8adb67 --- /dev/null +++ b/tools/gyp/test/rules/variables/src/input_ext.c @@ -0,0 +1,9 @@ +// 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. + +#include + +void input_ext() { + printf("input_ext\n"); +} diff --git a/tools/gyp/test/rules/variables/src/input_name/test.c b/tools/gyp/test/rules/variables/src/input_name/test.c new file mode 100644 index 00000000000000..e28b74d1158ab5 --- /dev/null +++ b/tools/gyp/test/rules/variables/src/input_name/test.c @@ -0,0 +1,9 @@ +// 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. + +#include + +void input_name() { + printf("input_name\n"); +} diff --git a/tools/gyp/test/rules/variables/src/input_path/subdir/test.c b/tools/gyp/test/rules/variables/src/input_path/subdir/test.c new file mode 100644 index 00000000000000..403dbbda4cf3d5 --- /dev/null +++ b/tools/gyp/test/rules/variables/src/input_path/subdir/test.c @@ -0,0 +1,9 @@ +// 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. + +#include + +void input_path() { + printf("input_path\n"); +} diff --git a/tools/gyp/test/rules/variables/src/subdir/input_dirname.c b/tools/gyp/test/rules/variables/src/subdir/input_dirname.c new file mode 100644 index 00000000000000..40cecd87d9ff3e --- /dev/null +++ b/tools/gyp/test/rules/variables/src/subdir/input_dirname.c @@ -0,0 +1,9 @@ +// 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. + +#include + +void input_dirname() { + printf("input_dirname\n"); +} diff --git a/tools/gyp/test/rules/variables/src/subdir/test.c b/tools/gyp/test/rules/variables/src/subdir/test.c new file mode 100644 index 00000000000000..6c0280b8adf9f4 --- /dev/null +++ b/tools/gyp/test/rules/variables/src/subdir/test.c @@ -0,0 +1,18 @@ +// 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. + +extern void input_root(); +extern void input_dirname(); +extern void input_path(); +extern void input_ext(); +extern void input_name(); + +int main() { + input_root(); + input_dirname(); + input_path(); + input_ext(); + input_name(); + return 0; +} diff --git a/tools/gyp/test/rules/variables/src/test.input_root.c b/tools/gyp/test/rules/variables/src/test.input_root.c new file mode 100644 index 00000000000000..33a7740a5cb939 --- /dev/null +++ b/tools/gyp/test/rules/variables/src/test.input_root.c @@ -0,0 +1,9 @@ +// 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. + +#include + +void input_root() { + printf("input_root\n"); +} diff --git a/tools/gyp/test/rules/variables/src/variables.gyp b/tools/gyp/test/rules/variables/src/variables.gyp new file mode 100644 index 00000000000000..6debba12e345bb --- /dev/null +++ b/tools/gyp/test/rules/variables/src/variables.gyp @@ -0,0 +1,40 @@ +# 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. + +{ + 'target_defaults': { + # This test shouldn't ever actually need to execute its rules: there's no + # command line that generates any output anyway. However, there's something + # slightly broken in either ninja or (maybe more likely?) on the win32 VM + # gypbots that breaks dependency checking and causes this rule to want to + # run. When it does run, the cygwin path is wrong, so the do-nothing step + # fails. + # TODO: Investigate and fix whatever's actually failing and remove this. + 'msvs_cygwin_dirs': ['../../../../../../<(DEPTH)/third_party/cygwin'], + }, + 'targets': [ + { + 'target_name': 'all_rule_variables', + 'type': 'executable', + 'sources': [ + 'subdir/test.c', + ], + 'rules': [ + { + 'rule_name': 'rule_variable', + 'extension': 'c', + 'outputs': [ + '<(RULE_INPUT_ROOT).input_root.c', + '<(RULE_INPUT_DIRNAME)/input_dirname.c', + 'input_path/<(RULE_INPUT_PATH)', + 'input_ext<(RULE_INPUT_EXT)', + 'input_name/<(RULE_INPUT_NAME)', + ], + 'action': [], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/same-gyp-name/gyptest-all.py b/tools/gyp/test/same-gyp-name/gyptest-all.py new file mode 100644 index 00000000000000..cda1a72d4d1e40 --- /dev/null +++ b/tools/gyp/test/same-gyp-name/gyptest-all.py @@ -0,0 +1,38 @@ +#!/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. + +""" +Build a .gyp that depends on 2 gyp files with the same name. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('all.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('all.gyp', test.ALL, chdir='relocate/src') + +expect1 = """\ +Hello from main1.cc +""" + +expect2 = """\ +Hello from main2.cc +""" + +if test.format == 'xcode': + chdir1 = 'relocate/src/subdir1' + chdir2 = 'relocate/src/subdir2' +else: + chdir1 = chdir2 = 'relocate/src' + +test.run_built_executable('program1', chdir=chdir1, stdout=expect1) +test.run_built_executable('program2', chdir=chdir2, stdout=expect2) + +test.pass_test() diff --git a/tools/gyp/test/same-gyp-name/gyptest-default.py b/tools/gyp/test/same-gyp-name/gyptest-default.py new file mode 100644 index 00000000000000..5e4bba0012e5bb --- /dev/null +++ b/tools/gyp/test/same-gyp-name/gyptest-default.py @@ -0,0 +1,38 @@ +#!/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. + +""" +Build a .gyp that depends on 2 gyp files with the same name. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('all.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('all.gyp', chdir='relocate/src') + +expect1 = """\ +Hello from main1.cc +""" + +expect2 = """\ +Hello from main2.cc +""" + +if test.format == 'xcode': + chdir1 = 'relocate/src/subdir1' + chdir2 = 'relocate/src/subdir2' +else: + chdir1 = chdir2 = 'relocate/src' + +test.run_built_executable('program1', chdir=chdir1, stdout=expect1) +test.run_built_executable('program2', chdir=chdir2, stdout=expect2) + +test.pass_test() diff --git a/tools/gyp/test/same-gyp-name/gyptest-library.py b/tools/gyp/test/same-gyp-name/gyptest-library.py new file mode 100644 index 00000000000000..957a4a52d64cac --- /dev/null +++ b/tools/gyp/test/same-gyp-name/gyptest-library.py @@ -0,0 +1,20 @@ +#!/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 a dependency on two gyp files with the same name do not create a +uid collision in the resulting generated xcode file. +""" + +import TestGyp + +import sys + +test = TestGyp.TestGyp() + +test.run_gyp('test.gyp', chdir='library') + +test.pass_test() diff --git a/tools/gyp/test/same-gyp-name/library/one/sub.gyp b/tools/gyp/test/same-gyp-name/library/one/sub.gyp new file mode 100644 index 00000000000000..1bed941e547f30 --- /dev/null +++ b/tools/gyp/test/same-gyp-name/library/one/sub.gyp @@ -0,0 +1,11 @@ +# 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': 'one', + 'type': 'static_library', + }, + ], +} diff --git a/tools/gyp/test/same-gyp-name/library/test.gyp b/tools/gyp/test/same-gyp-name/library/test.gyp new file mode 100644 index 00000000000000..552a77ed7eef2a --- /dev/null +++ b/tools/gyp/test/same-gyp-name/library/test.gyp @@ -0,0 +1,15 @@ +# 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': 'duplicate_names', + 'type': 'shared_library', + 'dependencies': [ + 'one/sub.gyp:one', + 'two/sub.gyp:two', + ], + }, + ], +} diff --git a/tools/gyp/test/same-gyp-name/library/two/sub.gyp b/tools/gyp/test/same-gyp-name/library/two/sub.gyp new file mode 100644 index 00000000000000..934c98a496e38b --- /dev/null +++ b/tools/gyp/test/same-gyp-name/library/two/sub.gyp @@ -0,0 +1,11 @@ +# 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': 'two', + 'type': 'static_library', + }, + ], +} diff --git a/tools/gyp/test/same-gyp-name/src/all.gyp b/tools/gyp/test/same-gyp-name/src/all.gyp new file mode 100644 index 00000000000000..229f02ea845c77 --- /dev/null +++ b/tools/gyp/test/same-gyp-name/src/all.gyp @@ -0,0 +1,16 @@ +# 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': 'all_exes', + 'type': 'none', + 'dependencies': [ + 'subdir1/executable.gyp:*', + 'subdir2/executable.gyp:*', + ], + }, + ], +} diff --git a/tools/gyp/test/same-gyp-name/src/subdir1/executable.gyp b/tools/gyp/test/same-gyp-name/src/subdir1/executable.gyp new file mode 100644 index 00000000000000..82483b4c69666d --- /dev/null +++ b/tools/gyp/test/same-gyp-name/src/subdir1/executable.gyp @@ -0,0 +1,15 @@ +# 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': 'program1', + 'type': 'executable', + 'sources': [ + 'main1.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/same-gyp-name/src/subdir1/main1.cc b/tools/gyp/test/same-gyp-name/src/subdir1/main1.cc new file mode 100644 index 00000000000000..3645558324d720 --- /dev/null +++ b/tools/gyp/test/same-gyp-name/src/subdir1/main1.cc @@ -0,0 +1,6 @@ +#include + +int main() { + printf("Hello from main1.cc\n"); + return 0; +} diff --git a/tools/gyp/test/same-gyp-name/src/subdir2/executable.gyp b/tools/gyp/test/same-gyp-name/src/subdir2/executable.gyp new file mode 100644 index 00000000000000..e3537013eb1815 --- /dev/null +++ b/tools/gyp/test/same-gyp-name/src/subdir2/executable.gyp @@ -0,0 +1,15 @@ +# 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': 'program2', + 'type': 'executable', + 'sources': [ + 'main2.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/same-gyp-name/src/subdir2/main2.cc b/tools/gyp/test/same-gyp-name/src/subdir2/main2.cc new file mode 100644 index 00000000000000..0c724dee35fe00 --- /dev/null +++ b/tools/gyp/test/same-gyp-name/src/subdir2/main2.cc @@ -0,0 +1,6 @@ +#include + +int main() { + printf("Hello from main2.cc\n"); + return 0; +} diff --git a/tools/gyp/test/same-rule-output-file-name/gyptest-all.py b/tools/gyp/test/same-rule-output-file-name/gyptest-all.py new file mode 100644 index 00000000000000..964e6b7721a702 --- /dev/null +++ b/tools/gyp/test/same-rule-output-file-name/gyptest-all.py @@ -0,0 +1,23 @@ +#!/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. + +""" +Tests the use of rules with the same output file name. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('subdirs.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('subdirs.gyp', test.ALL, chdir='relocate/src') +test.must_exist('relocate/src/subdir1/rule.txt') +test.must_exist('relocate/src/subdir2/rule.txt') + +test.pass_test() diff --git a/tools/gyp/test/same-rule-output-file-name/src/subdir1/subdir1.gyp b/tools/gyp/test/same-rule-output-file-name/src/subdir1/subdir1.gyp new file mode 100644 index 00000000000000..bff381a5a51037 --- /dev/null +++ b/tools/gyp/test/same-rule-output-file-name/src/subdir1/subdir1.gyp @@ -0,0 +1,30 @@ +# 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': 'target1', + 'type': 'none', + 'sources': [ + '../touch.py' + ], + 'rules': [ + { + 'rule_name': 'rule1', + 'extension': 'py', + 'inputs': [], + 'outputs': [ + 'rule.txt', + ], + 'action': [ + 'python', '../touch.py', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/same-rule-output-file-name/src/subdir2/subdir2.gyp b/tools/gyp/test/same-rule-output-file-name/src/subdir2/subdir2.gyp new file mode 100644 index 00000000000000..12a35600a3118c --- /dev/null +++ b/tools/gyp/test/same-rule-output-file-name/src/subdir2/subdir2.gyp @@ -0,0 +1,30 @@ +# 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': 'target2', + 'type': 'none', + 'sources': [ + '../touch.py' + ], + 'rules': [ + { + 'rule_name': 'rule2', + 'extension': 'py', + 'inputs': [], + 'outputs': [ + 'rule.txt', + ], + 'action': [ + 'python', '../touch.py', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/same-rule-output-file-name/src/subdirs.gyp b/tools/gyp/test/same-rule-output-file-name/src/subdirs.gyp new file mode 100644 index 00000000000000..25259a38f4e583 --- /dev/null +++ b/tools/gyp/test/same-rule-output-file-name/src/subdirs.gyp @@ -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': 'subdirs', + 'type': 'none', + 'dependencies': [ + 'subdir1/subdir1.gyp:*', + 'subdir2/subdir2.gyp:*', + ], + }, + ], +} diff --git a/tools/gyp/test/same-rule-output-file-name/src/touch.py b/tools/gyp/test/same-rule-output-file-name/src/touch.py new file mode 100644 index 00000000000000..2291e9cc560430 --- /dev/null +++ b/tools/gyp/test/same-rule-output-file-name/src/touch.py @@ -0,0 +1,11 @@ +#!/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. + +import sys + +f = open(sys.argv[1], 'w+') +f.write('Hello from touch.py\n') +f.close() diff --git a/tools/gyp/test/same-source-file-name/gyptest-all.py b/tools/gyp/test/same-source-file-name/gyptest-all.py new file mode 100644 index 00000000000000..4c215027c2ae8a --- /dev/null +++ b/tools/gyp/test/same-source-file-name/gyptest-all.py @@ -0,0 +1,34 @@ +#!/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. + +""" +Build a .gyp with two targets that share a common .c source file. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('all.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('all.gyp', test.ALL, chdir='relocate/src') + +expect1 = """\ +Hello from prog1.c +Hello prog1 from func.c +""" + +expect2 = """\ +Hello from prog2.c +Hello prog2 from func.c +""" + +test.run_built_executable('prog1', chdir='relocate/src', stdout=expect1) +test.run_built_executable('prog2', chdir='relocate/src', stdout=expect2) + +test.pass_test() diff --git a/tools/gyp/test/same-source-file-name/gyptest-default.py b/tools/gyp/test/same-source-file-name/gyptest-default.py new file mode 100644 index 00000000000000..98757c26971564 --- /dev/null +++ b/tools/gyp/test/same-source-file-name/gyptest-default.py @@ -0,0 +1,34 @@ +#!/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. + +""" +Build a .gyp with two targets that share a common .c source file. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('all.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('all.gyp', chdir='relocate/src') + +expect1 = """\ +Hello from prog1.c +Hello prog1 from func.c +""" + +expect2 = """\ +Hello from prog2.c +Hello prog2 from func.c +""" + +test.run_built_executable('prog1', chdir='relocate/src', stdout=expect1) +test.run_built_executable('prog2', chdir='relocate/src', stdout=expect2) + +test.pass_test() diff --git a/tools/gyp/test/same-source-file-name/gyptest-pass-executable.py b/tools/gyp/test/same-source-file-name/gyptest-pass-executable.py new file mode 100644 index 00000000000000..1a3dcda23d5669 --- /dev/null +++ b/tools/gyp/test/same-source-file-name/gyptest-pass-executable.py @@ -0,0 +1,33 @@ +#!/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 executable targets which have several files +with the same basename. +""" + +import TestGyp + +# While MSVS supports building executables that contain several files with the +# same name, the msvs gyp generator does not. +test = TestGyp.TestGyp(formats=['!msvs']) + +test.run_gyp('double-executable.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('double-executable.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from prog3.c +Hello prog3 from func.c +Hello prog3 from subdir1/func.c +Hello prog3 from subdir2/func.c +""" + +test.run_built_executable('prog3', chdir='relocate/src', stdout=expect) + +test.pass_test() diff --git a/tools/gyp/test/same-source-file-name/gyptest-pass-shared.py b/tools/gyp/test/same-source-file-name/gyptest-pass-shared.py new file mode 100644 index 00000000000000..a498f1a8460ba4 --- /dev/null +++ b/tools/gyp/test/same-source-file-name/gyptest-pass-shared.py @@ -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 --git a/tools/gyp/test/same-source-file-name/gyptest-static.py b/tools/gyp/test/same-source-file-name/gyptest-static.py new file mode 100644 index 00000000000000..e9a59032c86ef9 --- /dev/null +++ b/tools/gyp/test/same-source-file-name/gyptest-static.py @@ -0,0 +1,20 @@ +#!/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() + +test.run_gyp('double-static.gyp', chdir='src', status=1, stderr=None) +test.pass_test() diff --git a/tools/gyp/test/same-source-file-name/src/all.gyp b/tools/gyp/test/same-source-file-name/src/all.gyp new file mode 100644 index 00000000000000..4fe052c6687143 --- /dev/null +++ b/tools/gyp/test/same-source-file-name/src/all.gyp @@ -0,0 +1,30 @@ +# 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': 'prog1', + 'type': 'executable', + 'defines': [ + 'PROG="prog1"', + ], + 'sources': [ + 'prog1.c', + 'func.c', + ], + }, + { + 'target_name': 'prog2', + 'type': 'executable', + 'defines': [ + 'PROG="prog2"', + ], + 'sources': [ + 'prog2.c', + 'func.c', + ], + }, + ], +} diff --git a/tools/gyp/test/same-source-file-name/src/double-executable.gyp b/tools/gyp/test/same-source-file-name/src/double-executable.gyp new file mode 100644 index 00000000000000..477bd87e0d8c50 --- /dev/null +++ b/tools/gyp/test/same-source-file-name/src/double-executable.gyp @@ -0,0 +1,21 @@ +# 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': 'prog3', + 'type': 'executable', + 'sources': [ + 'prog3.c', + 'func.c', + 'subdir1/func.c', + 'subdir2/func.c', + ], + 'defines': [ + 'PROG="prog3"', + ], + }, + ], +} diff --git a/tools/gyp/test/same-source-file-name/src/double-shared.gyp b/tools/gyp/test/same-source-file-name/src/double-shared.gyp new file mode 100644 index 00000000000000..438b50f3f1168d --- /dev/null +++ b/tools/gyp/test/same-source-file-name/src/double-shared.gyp @@ -0,0 +1,27 @@ +# 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': 'lib', + 'product_name': 'test_shared_lib', + 'type': 'shared_library', + 'sources': [ + 'prog2.c', + 'func.c', + 'subdir1/func.c', + 'subdir2/func.c', + ], + 'defines': [ + 'PROG="prog2"', + ], + 'conditions': [ + ['OS=="linux"', { + 'cflags': ['-fPIC'], + }], + ], + }, + ], +} diff --git a/tools/gyp/test/same-source-file-name/src/double-static.gyp b/tools/gyp/test/same-source-file-name/src/double-static.gyp new file mode 100644 index 00000000000000..e49c0e1251020c --- /dev/null +++ b/tools/gyp/test/same-source-file-name/src/double-static.gyp @@ -0,0 +1,22 @@ +# 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': 'lib', + 'product_name': 'test_static_lib', + 'type': 'static_library', + 'sources': [ + 'prog1.c', + 'func.c', + 'subdir1/func.c', + 'subdir2/func.c', + ], + 'defines': [ + 'PROG="prog1"', + ], + }, + ], +} diff --git a/tools/gyp/test/same-source-file-name/src/func.c b/tools/gyp/test/same-source-file-name/src/func.c new file mode 100644 index 00000000000000..e069c692a69c91 --- /dev/null +++ b/tools/gyp/test/same-source-file-name/src/func.c @@ -0,0 +1,6 @@ +#include + +void func(void) +{ + printf("Hello %s from func.c\n", PROG); +} diff --git a/tools/gyp/test/same-source-file-name/src/prog1.c b/tools/gyp/test/same-source-file-name/src/prog1.c new file mode 100644 index 00000000000000..604e2b9c98f4d1 --- /dev/null +++ b/tools/gyp/test/same-source-file-name/src/prog1.c @@ -0,0 +1,16 @@ +#include + +extern void func(void); + +int main(void) +{ + printf("Hello from prog1.c\n"); + func(); + /* + * Uncomment to test same-named files in different directories, + * which Visual Studio doesn't support. + subdir1_func(); + subdir2_func(); + */ + return 0; +} diff --git a/tools/gyp/test/same-source-file-name/src/prog2.c b/tools/gyp/test/same-source-file-name/src/prog2.c new file mode 100644 index 00000000000000..466ee35003c3fc --- /dev/null +++ b/tools/gyp/test/same-source-file-name/src/prog2.c @@ -0,0 +1,16 @@ +#include + +extern void func(void); + +int main(void) +{ + printf("Hello from prog2.c\n"); + func(); + /* + * Uncomment to test same-named files in different directories, + * which Visual Studio doesn't support. + subdir1_func(); + subdir2_func(); + */ + return 0; +} diff --git a/tools/gyp/test/same-source-file-name/src/prog3.c b/tools/gyp/test/same-source-file-name/src/prog3.c new file mode 100644 index 00000000000000..34d495ce08d056 --- /dev/null +++ b/tools/gyp/test/same-source-file-name/src/prog3.c @@ -0,0 +1,18 @@ +// 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 + +extern void func(void); +extern void subdir1_func(void); +extern void subdir2_func(void); + +int main(void) +{ + printf("Hello from prog3.c\n"); + func(); + subdir1_func(); + subdir2_func(); + return 0; +} diff --git a/tools/gyp/test/same-source-file-name/src/subdir1/func.c b/tools/gyp/test/same-source-file-name/src/subdir1/func.c new file mode 100644 index 00000000000000..b73450d105ef30 --- /dev/null +++ b/tools/gyp/test/same-source-file-name/src/subdir1/func.c @@ -0,0 +1,6 @@ +#include + +void subdir1_func(void) +{ + printf("Hello %s from subdir1/func.c\n", PROG); +} diff --git a/tools/gyp/test/same-source-file-name/src/subdir2/func.c b/tools/gyp/test/same-source-file-name/src/subdir2/func.c new file mode 100644 index 00000000000000..0248b5720e0c92 --- /dev/null +++ b/tools/gyp/test/same-source-file-name/src/subdir2/func.c @@ -0,0 +1,6 @@ +#include + +void subdir2_func(void) +{ + printf("Hello %s from subdir2/func.c\n", PROG); +} diff --git a/tools/gyp/test/same-target-name-different-directory/gyptest-all.py b/tools/gyp/test/same-target-name-different-directory/gyptest-all.py new file mode 100644 index 00000000000000..365c949477980b --- /dev/null +++ b/tools/gyp/test/same-target-name-different-directory/gyptest-all.py @@ -0,0 +1,29 @@ +""" +Test cases when multiple targets in different directories have the same name. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['ninja', 'make']) +test.run_gyp('subdirs.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +# Test that we build all targets. +test.build('subdirs.gyp', 'target', chdir='relocate/src') +test.must_exist('relocate/src/subdir1/action1.txt') +test.must_exist('relocate/src/subdir2/action2.txt') + +# Test that we build all targets using the correct actions, even if they have +# the same names. +test.build('subdirs.gyp', 'target_same_action_name', chdir='relocate/src') +test.must_exist('relocate/src/subdir1/action.txt') +test.must_exist('relocate/src/subdir2/action.txt') + +# Test that we build all targets using the correct rules, even if they have +# the same names. +test.build('subdirs.gyp', 'target_same_rule_name', chdir='relocate/src') +test.must_exist('relocate/src/subdir1/rule.txt') +test.must_exist('relocate/src/subdir2/rule.txt') + +test.pass_test() diff --git a/tools/gyp/test/same-target-name-different-directory/src/subdir1/subdir1.gyp b/tools/gyp/test/same-target-name-different-directory/src/subdir1/subdir1.gyp new file mode 100644 index 00000000000000..d4ec2e679acf16 --- /dev/null +++ b/tools/gyp/test/same-target-name-different-directory/src/subdir1/subdir1.gyp @@ -0,0 +1,66 @@ +# 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': 'target', + 'type': 'none', + 'actions': [ + { + 'action_name': 'action1', + 'inputs': [], + 'outputs': [ + 'action1.txt', + ], + 'action': [ + 'python', '../touch.py', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + { + 'target_name': 'target_same_action_name', + 'type': 'none', + 'actions': [ + { + 'action_name': 'action', + 'inputs': [], + 'outputs': [ + 'action.txt', + ], + 'action': [ + 'python', '../touch.py', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + { + 'target_name': 'target_same_rule_name', + 'type': 'none', + 'sources': [ + '../touch.py' + ], + 'rules': [ + { + 'rule_name': 'rule', + 'extension': 'py', + 'inputs': [], + 'outputs': [ + 'rule.txt', + ], + 'action': [ + 'python', '../touch.py', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/same-target-name-different-directory/src/subdir2/subdir2.gyp b/tools/gyp/test/same-target-name-different-directory/src/subdir2/subdir2.gyp new file mode 100644 index 00000000000000..9006d450b26218 --- /dev/null +++ b/tools/gyp/test/same-target-name-different-directory/src/subdir2/subdir2.gyp @@ -0,0 +1,66 @@ +# 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': 'target', + 'type': 'none', + 'actions': [ + { + 'action_name': 'action2', + 'inputs': [], + 'outputs': [ + 'action2.txt', + ], + 'action': [ + 'python', '../touch.py', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + { + 'target_name': 'target_same_action_name', + 'type': 'none', + 'actions': [ + { + 'action_name': 'action', + 'inputs': [], + 'outputs': [ + 'action.txt', + ], + 'action': [ + 'python', '../touch.py', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + { + 'target_name': 'target_same_rule_name', + 'type': 'none', + 'sources': [ + '../touch.py' + ], + 'rules': [ + { + 'rule_name': 'rule', + 'extension': 'py', + 'inputs': [], + 'outputs': [ + 'rule.txt', + ], + 'action': [ + 'python', '../touch.py', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/same-target-name-different-directory/src/subdirs.gyp b/tools/gyp/test/same-target-name-different-directory/src/subdirs.gyp new file mode 100644 index 00000000000000..65413e73b2b8ca --- /dev/null +++ b/tools/gyp/test/same-target-name-different-directory/src/subdirs.gyp @@ -0,0 +1,16 @@ +# Copyright (c) 2010 Google 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': 'subdirs', + 'type': 'none', + 'dependencies': [ + 'subdir1/subdir1.gyp:*', + 'subdir2/subdir2.gyp:*', + ], + }, + ], +} diff --git a/tools/gyp/test/same-target-name-different-directory/src/touch.py b/tools/gyp/test/same-target-name-different-directory/src/touch.py new file mode 100644 index 00000000000000..2291e9cc560430 --- /dev/null +++ b/tools/gyp/test/same-target-name-different-directory/src/touch.py @@ -0,0 +1,11 @@ +#!/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. + +import sys + +f = open(sys.argv[1], 'w+') +f.write('Hello from touch.py\n') +f.close() diff --git a/tools/gyp/test/same-target-name/gyptest-same-target-name.py b/tools/gyp/test/same-target-name/gyptest-same-target-name.py new file mode 100644 index 00000000000000..bfe5540f31223f --- /dev/null +++ b/tools/gyp/test/same-target-name/gyptest-same-target-name.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python + +# Copyright (c) 2010 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Check that duplicate targets in a directory gives an error. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +# Require that gyp files with duplicate targets spit out an error. +test.run_gyp('all.gyp', chdir='src', status=1, stderr=None) + +test.pass_test() diff --git a/tools/gyp/test/same-target-name/src/all.gyp b/tools/gyp/test/same-target-name/src/all.gyp new file mode 100644 index 00000000000000..ac16976da6af14 --- /dev/null +++ b/tools/gyp/test/same-target-name/src/all.gyp @@ -0,0 +1,16 @@ +# Copyright (c) 2010 Google 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_exes', + 'type': 'none', + 'dependencies': [ + 'executable1.gyp:*', + 'executable2.gyp:*', + ], + }, + ], +} diff --git a/tools/gyp/test/same-target-name/src/executable1.gyp b/tools/gyp/test/same-target-name/src/executable1.gyp new file mode 100644 index 00000000000000..3c492c1b375603 --- /dev/null +++ b/tools/gyp/test/same-target-name/src/executable1.gyp @@ -0,0 +1,15 @@ +# Copyright (c) 2010 Google 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': [ + 'main1.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/same-target-name/src/executable2.gyp b/tools/gyp/test/same-target-name/src/executable2.gyp new file mode 100644 index 00000000000000..41e84a61c679bf --- /dev/null +++ b/tools/gyp/test/same-target-name/src/executable2.gyp @@ -0,0 +1,15 @@ +# Copyright (c) 2010 Google 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': [ + 'main2.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/sanitize-rule-names/blah.S b/tools/gyp/test/sanitize-rule-names/blah.S new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/sanitize-rule-names/gyptest-sanitize-rule-names.py b/tools/gyp/test/sanitize-rule-names/gyptest-sanitize-rule-names.py new file mode 100644 index 00000000000000..968a0ce5ce48e8 --- /dev/null +++ b/tools/gyp/test/sanitize-rule-names/gyptest-sanitize-rule-names.py @@ -0,0 +1,17 @@ +#!/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. + +""" +Make sure rule names with non-"normal" characters in them don't cause +broken build files. This test was originally causing broken .ninja files. +""" + +import TestGyp + +test = TestGyp.TestGyp() +test.run_gyp('sanitize-rule-names.gyp') +test.build('sanitize-rule-names.gyp', test.ALL) +test.pass_test() diff --git a/tools/gyp/test/sanitize-rule-names/hello.cc b/tools/gyp/test/sanitize-rule-names/hello.cc new file mode 100644 index 00000000000000..1711567ef56670 --- /dev/null +++ b/tools/gyp/test/sanitize-rule-names/hello.cc @@ -0,0 +1,7 @@ +// 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. + +int main() { + return 0; +} diff --git a/tools/gyp/test/sanitize-rule-names/sanitize-rule-names.gyp b/tools/gyp/test/sanitize-rule-names/sanitize-rule-names.gyp new file mode 100644 index 00000000000000..184253e966df36 --- /dev/null +++ b/tools/gyp/test/sanitize-rule-names/sanitize-rule-names.gyp @@ -0,0 +1,27 @@ +# 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': 's_test', + 'type': 'executable', + 'rules': [ + { + # Make sure this rule name doesn't cause an invalid ninja file. + 'rule_name': 'rule name with odd characters ()/', + 'extension': 'S', + 'outputs': ['outfile'], + 'msvs_cygwin_shell': 0, + 'msvs_quote_cmd': 0, + 'action': ['python', 'script.py', '<(RULE_INPUT_PATH)', 'outfile'], + }, + ], + 'sources': [ + 'blah.S', + 'hello.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/sanitize-rule-names/script.py b/tools/gyp/test/sanitize-rule-names/script.py new file mode 100644 index 00000000000000..ae2efa1df46901 --- /dev/null +++ b/tools/gyp/test/sanitize-rule-names/script.py @@ -0,0 +1,10 @@ +#!/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. + +import shutil +import sys + +shutil.copyfile(*sys.argv[1:]) diff --git a/tools/gyp/test/self-dependency/common.gypi b/tools/gyp/test/self-dependency/common.gypi new file mode 100644 index 00000000000000..aae221a5dd0109 --- /dev/null +++ b/tools/gyp/test/self-dependency/common.gypi @@ -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. + +# A common file that other .gyp files include. +# Makes every target in the project depend on dep.gyp:dep. +{ + 'target_defaults': { + 'dependencies': [ + 'dep.gyp:dep', + ], + }, +} diff --git a/tools/gyp/test/self-dependency/dep.gyp b/tools/gyp/test/self-dependency/dep.gyp new file mode 100644 index 00000000000000..2b6c9dda854fe3 --- /dev/null +++ b/tools/gyp/test/self-dependency/dep.gyp @@ -0,0 +1,23 @@ +# 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. + +# dep.gyp contains a target dep, on which all the targets in the project +# depend. This means there's a self-dependency of dep on itself, which is +# pruned by setting prune_self_dependency to 1. + +{ + 'includes': [ + 'common.gypi', + ], + 'targets': [ + { + 'target_name': 'dep', + 'type': 'none', + 'variables': { + # Without this GYP will report a cycle in dependency graph. + 'prune_self_dependency': 1, + }, + }, + ], +} diff --git a/tools/gyp/test/self-dependency/gyptest-self-dependency.py b/tools/gyp/test/self-dependency/gyptest-self-dependency.py new file mode 100644 index 00000000000000..82fab271c56fa5 --- /dev/null +++ b/tools/gyp/test/self-dependency/gyptest-self-dependency.py @@ -0,0 +1,19 @@ +#!/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 pulling in a dependency a second time in a conditional works for +shared_library targets. Regression test for http://crbug.com/122588 +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('self_dependency.gyp') + +# If running gyp worked, all is well. +test.pass_test() diff --git a/tools/gyp/test/self-dependency/self_dependency.gyp b/tools/gyp/test/self-dependency/self_dependency.gyp new file mode 100644 index 00000000000000..0ca76c669b6a68 --- /dev/null +++ b/tools/gyp/test/self-dependency/self_dependency.gyp @@ -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. + +{ + 'includes': [ + 'common.gypi', + ], + 'targets': [ + { + 'target_name': 'a', + 'type': 'none', + }, + ], +} diff --git a/tools/gyp/test/sibling/gyptest-all.py b/tools/gyp/test/sibling/gyptest-all.py new file mode 100644 index 00000000000000..318e1a3d843ba6 --- /dev/null +++ b/tools/gyp/test/sibling/gyptest-all.py @@ -0,0 +1,42 @@ +#!/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. + +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') + +chdir = 'src/build' + +# The top-level Makefile is in the directory where gyp was run. +# 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', 'cmake'): + chdir = 'src' + +if test.format == 'xcode': + chdir = 'src/prog1' +test.run_built_executable('program1', + chdir=chdir, + stdout="Hello from prog1.c\n") + +if test.format == 'xcode': + chdir = 'src/prog2' +test.run_built_executable('program2', + chdir=chdir, + stdout="Hello from prog2.c\n") + +test.pass_test() diff --git a/tools/gyp/test/sibling/gyptest-relocate.py b/tools/gyp/test/sibling/gyptest-relocate.py new file mode 100644 index 00000000000000..05fa9d96fed11a --- /dev/null +++ b/tools/gyp/test/sibling/gyptest-relocate.py @@ -0,0 +1,44 @@ +#!/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. + +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') + +test.build('build/all.gyp', test.ALL, chdir='relocate/src') + +chdir = 'relocate/src/build' + +# The top-level Makefile is in the directory where gyp was run. +# 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', 'cmake'): + chdir = 'relocate/src' + +if test.format == 'xcode': + chdir = 'relocate/src/prog1' +test.run_built_executable('program1', + chdir=chdir, + stdout="Hello from prog1.c\n") + +if test.format == 'xcode': + chdir = 'relocate/src/prog2' +test.run_built_executable('program2', + chdir=chdir, + stdout="Hello from prog2.c\n") + +test.pass_test() diff --git a/tools/gyp/test/sibling/src/build/all.gyp b/tools/gyp/test/sibling/src/build/all.gyp new file mode 100644 index 00000000000000..79c80c9363524d --- /dev/null +++ b/tools/gyp/test/sibling/src/build/all.gyp @@ -0,0 +1,16 @@ +# 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': 'All', + 'type': 'none', + 'dependencies': [ + '../prog1/prog1.gyp:*', + '../prog2/prog2.gyp:*', + ], + }, + ], +} diff --git a/tools/gyp/test/sibling/src/prog1/prog1.c b/tools/gyp/test/sibling/src/prog1/prog1.c new file mode 100644 index 00000000000000..218e99401cb259 --- /dev/null +++ b/tools/gyp/test/sibling/src/prog1/prog1.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + printf("Hello from prog1.c\n"); + return 0; +} diff --git a/tools/gyp/test/sibling/src/prog1/prog1.gyp b/tools/gyp/test/sibling/src/prog1/prog1.gyp new file mode 100644 index 00000000000000..4532e4be101d00 --- /dev/null +++ b/tools/gyp/test/sibling/src/prog1/prog1.gyp @@ -0,0 +1,15 @@ +# 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': 'program1', + 'type': 'executable', + 'sources': [ + 'prog1.c', + ], + }, + ], +} diff --git a/tools/gyp/test/sibling/src/prog2/prog2.c b/tools/gyp/test/sibling/src/prog2/prog2.c new file mode 100644 index 00000000000000..12a31883b93a99 --- /dev/null +++ b/tools/gyp/test/sibling/src/prog2/prog2.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + printf("Hello from prog2.c\n"); + return 0; +} diff --git a/tools/gyp/test/sibling/src/prog2/prog2.gyp b/tools/gyp/test/sibling/src/prog2/prog2.gyp new file mode 100644 index 00000000000000..4cf7f6eb2f4f4a --- /dev/null +++ b/tools/gyp/test/sibling/src/prog2/prog2.gyp @@ -0,0 +1,15 @@ +# 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': 'program2', + 'type': 'executable', + 'sources': [ + 'prog2.c', + ], + }, + ], +} diff --git a/tools/gyp/test/small/gyptest-small.py b/tools/gyp/test/small/gyptest-small.py new file mode 100644 index 00000000000000..d70c99a0690736 --- /dev/null +++ b/tools/gyp/test/small/gyptest-small.py @@ -0,0 +1,53 @@ +#!/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. + +""" +Runs small tests. +""" + +import imp +import os +import sys +import unittest + + +# Add pylib to the import path (so tests can import their dependencies). +# This is consistent with the path.append done in the top file "gyp". +# This need to happen before we init TestGyp, which changes the cwd. +gyp_src_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) +sys.path.insert(0, gyp_src_root) + + +files_to_test = [ + 'common_test.py', + 'easy_xml_test.py', + 'generator_msvs_test.py', + 'NinjaWriter_test.py', + 'generator_xcode_test.py', + 'input_test.py', + 'MSVSSettings_test.py', +] +# Add new test suites here. + +# Collect all the suites from the above files. +suites = [] +for filename in files_to_test: + # Carve the module name out of the path. + name = os.path.splitext(filename)[0] + # Find the complete module path. + full_filename = os.path.join(gyp_src_root, 'gyp', 'unit_tests', filename) + # Load the module. + module = imp.load_source(name, full_filename) + # Add it to the list of test suites. + suites.append(unittest.defaultTestLoader.loadTestsFromModule(module)) +# Create combined suite. +all_tests = unittest.TestSuite(suites) + +# Run all the tests. +result = unittest.TextTestRunner(verbosity=2).run(all_tests) +if result.failures or result.errors: + sys.exit(1) + diff --git a/tools/gyp/test/standalone-static-library/gyptest-standalone-static-library.py b/tools/gyp/test/standalone-static-library/gyptest-standalone-static-library.py new file mode 100644 index 00000000000000..90e2750b3cdfff --- /dev/null +++ b/tools/gyp/test/standalone-static-library/gyptest-standalone-static-library.py @@ -0,0 +1,50 @@ +#!/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 build of a static_library with the standalone_static_library flag set. +""" + +import os +import subprocess +import sys +import TestGyp + +# standalone_static_library currently means two things: a specific output +# 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) +target_str = 'invalid.gyp:bad#target' +err = ['gyp: Target %s has type executable but standalone_static_library flag ' + 'is only valid for static_library type.' % target_str] +test.must_contain_all_lines(test.stderr(), err) + +# Build a valid standalone_static_library. +test.run_gyp('mylib.gyp') +test.build('mylib.gyp', target='prog') + +# Verify that the static library is copied to the correct location. +# We expect the library to be copied to $PRODUCT_DIR. +standalone_static_library_dir = test.EXECUTABLE +path_to_lib = os.path.split( + test.built_file_path('mylib', type=standalone_static_library_dir))[0] +lib_name = test.built_file_basename('mylib', type=test.STATIC_LIB) +path = os.path.join(path_to_lib, lib_name) +test.must_exist(path) + +# Verify that the program runs properly. +expect = 'hello from mylib.c\n' +test.run_built_executable('prog', stdout=expect) + +# Verify that libmylib.a contains symbols. "ar -x" fails on a 'thin' archive. +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 + +test.pass_test() diff --git a/tools/gyp/test/standalone-static-library/invalid.gyp b/tools/gyp/test/standalone-static-library/invalid.gyp new file mode 100644 index 00000000000000..54b32117e05ce2 --- /dev/null +++ b/tools/gyp/test/standalone-static-library/invalid.gyp @@ -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': 'bad', + 'type': 'executable', + 'standalone_static_library': 1, + 'sources': [ + 'prog.c', + ], + }, + ], +} \ No newline at end of file diff --git a/tools/gyp/test/standalone-static-library/mylib.c b/tools/gyp/test/standalone-static-library/mylib.c new file mode 100644 index 00000000000000..108be618c291fd --- /dev/null +++ b/tools/gyp/test/standalone-static-library/mylib.c @@ -0,0 +1,7 @@ +#include + +void print(void) +{ + printf("hello from mylib.c\n"); + return; +} diff --git a/tools/gyp/test/standalone-static-library/mylib.gyp b/tools/gyp/test/standalone-static-library/mylib.gyp new file mode 100644 index 00000000000000..2d191de3197ae5 --- /dev/null +++ b/tools/gyp/test/standalone-static-library/mylib.gyp @@ -0,0 +1,26 @@ +# 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': 'mylib', + 'type': 'static_library', + 'standalone_static_library': 1, + 'sources': [ + 'mylib.c', + ], + }, + { + 'target_name': 'prog', + 'type': 'executable', + 'sources': [ + 'prog.c', + ], + 'dependencies': [ + 'mylib', + ], + }, + ], +} diff --git a/tools/gyp/test/standalone-static-library/prog.c b/tools/gyp/test/standalone-static-library/prog.c new file mode 100644 index 00000000000000..8af5c90844be41 --- /dev/null +++ b/tools/gyp/test/standalone-static-library/prog.c @@ -0,0 +1,7 @@ +extern void print(void); + +int main(void) +{ + print(); + return 0; +} diff --git a/tools/gyp/test/standalone/gyptest-standalone.py b/tools/gyp/test/standalone/gyptest-standalone.py new file mode 100644 index 00000000000000..8fbd4361bcc9b3 --- /dev/null +++ b/tools/gyp/test/standalone/gyptest-standalone.py @@ -0,0 +1,36 @@ +#!/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 a project hierarchy created with the --generator-output= +option can be built even when it's relocated to a different path. +""" + +from __future__ import print_function + +import TestGyp +import os + +test = TestGyp.TestGyp() + +test.run_gyp('standalone.gyp', '-Gstandalone') + +# Look at all the files in the tree to make sure none +# of them reference the gyp file. +me = os.path.basename(__file__) +for root, dirs, files in os.walk("."): + for file in files: + # ignore me + if me in file: + continue + file = os.path.join(root, file) + contents = test.read(file) + if 'standalone.gyp' in contents: + print('gyp file referenced in generated output: %s' % file) + test.fail_test() + + +test.pass_test() diff --git a/tools/gyp/test/standalone/standalone.gyp b/tools/gyp/test/standalone/standalone.gyp new file mode 100644 index 00000000000000..b2a6785430393c --- /dev/null +++ b/tools/gyp/test/standalone/standalone.gyp @@ -0,0 +1,12 @@ +# 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' : 'foo', + 'type' : 'executable' + }, + ] +} diff --git a/tools/gyp/test/subdirectory/gyptest-SYMROOT-all.py b/tools/gyp/test/subdirectory/gyptest-SYMROOT-all.py new file mode 100644 index 00000000000000..9dfb8b05d4ed41 --- /dev/null +++ b/tools/gyp/test/subdirectory/gyptest-SYMROOT-all.py @@ -0,0 +1,36 @@ +#!/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 building a target and a subsidiary dependent target from a +.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. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('prog1.gyp', '-Dset_symroot=1', '--depth=.', chdir='src') + +test.relocate('src', 'relocate/src') + +# Suppress the test infrastructure's setting SYMROOT on the command line. +test.build('prog1.gyp', test.ALL, SYMROOT=None, chdir='relocate/src') + +test.run_built_executable('prog1', + stdout="Hello from prog1.c\n", + chdir='relocate/src') +test.run_built_executable('prog2', + stdout="Hello from prog2.c\n", + chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/subdirectory/gyptest-SYMROOT-default.py b/tools/gyp/test/subdirectory/gyptest-SYMROOT-default.py new file mode 100644 index 00000000000000..8796650905637f --- /dev/null +++ b/tools/gyp/test/subdirectory/gyptest-SYMROOT-default.py @@ -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 building a target and a subsidiary dependent target from a +.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. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('prog1.gyp', '-Dset_symroot=1', '--depth=.', chdir='src') + +test.relocate('src', 'relocate/src') + +# Suppress the test infrastructure's setting SYMROOT on the command line. +test.build('prog1.gyp', SYMROOT=None, chdir='relocate/src') + +test.run_built_executable('prog1', + stdout="Hello from prog1.c\n", + chdir='relocate/src') + +test.run_built_executable('prog2', + stdout="Hello from prog2.c\n", + chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/subdirectory/gyptest-subdir-all.py b/tools/gyp/test/subdirectory/gyptest-subdir-all.py new file mode 100644 index 00000000000000..7f2dacdb9a7480 --- /dev/null +++ b/tools/gyp/test/subdirectory/gyptest-subdir-all.py @@ -0,0 +1,26 @@ +""" +Verifies building a subsidiary dependent target from a .gyp file in a +subdirectory, without specifying an explicit output build directory, +and using the subdirectory's solution or project file as the entry point. +""" + +import TestGyp + +# Ninja doesn't support relocation. +# CMake produces a single CMakeLists.txt in the output directory. +test = TestGyp.TestGyp(formats=['!ninja', '!cmake']) + +test.run_gyp('prog1.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +chdir = 'relocate/src/subdir' +target = test.ALL + +test.build('prog2.gyp', target, chdir=chdir) + +test.built_file_must_not_exist('prog1', type=test.EXECUTABLE, chdir=chdir) + +test.run_built_executable('prog2', chdir=chdir, stdout="Hello from prog2.c\n") + +test.pass_test() diff --git a/tools/gyp/test/subdirectory/gyptest-subdir-default.py b/tools/gyp/test/subdirectory/gyptest-subdir-default.py new file mode 100644 index 00000000000000..2cb6659beb8a7c --- /dev/null +++ b/tools/gyp/test/subdirectory/gyptest-subdir-default.py @@ -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. + +""" +Verifies building a subsidiary dependent target from a .gyp file in a +subdirectory, without specifying an explicit output build directory, +and using the subdirectory's solution or project file as the entry point. +""" + +import TestGyp +import errno + +# Ninja doesn't support relocation. +# CMake produces a single CMakeLists.txt in the output directory. +test = TestGyp.TestGyp(formats=['!ninja', '!cmake']) + +test.run_gyp('prog1.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +chdir = 'relocate/src/subdir' + +test.build('prog2.gyp', chdir=chdir) + +test.built_file_must_not_exist('prog1', type=test.EXECUTABLE, chdir=chdir) + +test.run_built_executable('prog2', + chdir=chdir, + stdout="Hello from prog2.c\n") + +test.pass_test() diff --git a/tools/gyp/test/subdirectory/gyptest-subdir2-deep.py b/tools/gyp/test/subdirectory/gyptest-subdir2-deep.py new file mode 100644 index 00000000000000..48548982f8c5d4 --- /dev/null +++ b/tools/gyp/test/subdirectory/gyptest-subdir2-deep.py @@ -0,0 +1,25 @@ +#!/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 building a project rooted several layers under src_dir works. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('prog3.gyp', chdir='src/subdir/subdir2') + +test.relocate('src', 'relocate/src') + +test.build('prog3.gyp', test.ALL, chdir='relocate/src/subdir/subdir2') + +test.run_built_executable('prog3', + chdir='relocate/src/subdir/subdir2', + stdout="Hello from prog3.c\n") + +test.pass_test() diff --git a/tools/gyp/test/subdirectory/gyptest-top-all.py b/tools/gyp/test/subdirectory/gyptest-top-all.py new file mode 100644 index 00000000000000..b3c25b1f8d764b --- /dev/null +++ b/tools/gyp/test/subdirectory/gyptest-top-all.py @@ -0,0 +1,43 @@ +#!/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 building a target and a subsidiary dependent target from a +.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. + +There is a difference here in the default behavior of the underlying +build tools. Specifically, when building the entire "solution", Xcode +puts the output of each project relative to the .xcodeproj directory, +while Visual Studio (and our implementation of Make) put it +in a build directory relative to the "solution"--that is, the entry-point +from which you built the entire tree. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('prog1.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('prog1.gyp', test.ALL, chdir='relocate/src') + +test.run_built_executable('prog1', + stdout="Hello from prog1.c\n", + chdir='relocate/src') + +if test.format == 'xcode': + chdir = 'relocate/src/subdir' +else: + chdir = 'relocate/src' +test.run_built_executable('prog2', + chdir=chdir, + stdout="Hello from prog2.c\n") + +test.pass_test() diff --git a/tools/gyp/test/subdirectory/gyptest-top-default.py b/tools/gyp/test/subdirectory/gyptest-top-default.py new file mode 100644 index 00000000000000..2448dd98ea50dc --- /dev/null +++ b/tools/gyp/test/subdirectory/gyptest-top-default.py @@ -0,0 +1,43 @@ +#!/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 building a target and a subsidiary dependent target from a +.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. + +There is a difference here in the default behavior of the underlying +build tools. Specifically, when building the entire "solution", Xcode +puts the output of each project relative to the .xcodeproj directory, +while Visual Studio (and our implementation of Make) put it +in a build directory relative to the "solution"--that is, the entry-point +from which you built the entire tree. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('prog1.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('prog1.gyp', chdir='relocate/src') + +test.run_built_executable('prog1', + stdout="Hello from prog1.c\n", + chdir='relocate/src') + +if test.format == 'xcode': + chdir = 'relocate/src/subdir' +else: + chdir = 'relocate/src' +test.run_built_executable('prog2', + chdir=chdir, + stdout="Hello from prog2.c\n") + +test.pass_test() diff --git a/tools/gyp/test/subdirectory/src/prog1.c b/tools/gyp/test/subdirectory/src/prog1.c new file mode 100644 index 00000000000000..218e99401cb259 --- /dev/null +++ b/tools/gyp/test/subdirectory/src/prog1.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + printf("Hello from prog1.c\n"); + return 0; +} diff --git a/tools/gyp/test/subdirectory/src/prog1.gyp b/tools/gyp/test/subdirectory/src/prog1.gyp new file mode 100644 index 00000000000000..2aa66ce7d7f1fc --- /dev/null +++ b/tools/gyp/test/subdirectory/src/prog1.gyp @@ -0,0 +1,21 @@ +# 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. + +{ + 'includes': [ + 'symroot.gypi', + ], + 'targets': [ + { + 'target_name': 'prog1', + 'type': 'executable', + 'dependencies': [ + 'subdir/prog2.gyp:prog2', + ], + 'sources': [ + 'prog1.c', + ], + }, + ], +} diff --git a/tools/gyp/test/subdirectory/src/subdir/prog2.c b/tools/gyp/test/subdirectory/src/subdir/prog2.c new file mode 100644 index 00000000000000..12a31883b93a99 --- /dev/null +++ b/tools/gyp/test/subdirectory/src/subdir/prog2.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + printf("Hello from prog2.c\n"); + return 0; +} diff --git a/tools/gyp/test/subdirectory/src/subdir/prog2.gyp b/tools/gyp/test/subdirectory/src/subdir/prog2.gyp new file mode 100644 index 00000000000000..c6cd35f7f81eff --- /dev/null +++ b/tools/gyp/test/subdirectory/src/subdir/prog2.gyp @@ -0,0 +1,18 @@ +# 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. + +{ + 'includes': [ + '../symroot.gypi', + ], + 'targets': [ + { + 'target_name': 'prog2', + 'type': 'executable', + 'sources': [ + 'prog2.c', + ], + }, + ], +} diff --git a/tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.c b/tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.c new file mode 100644 index 00000000000000..a326dc61b6a25c --- /dev/null +++ b/tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + printf("Hello from prog3.c\n"); + return 0; +} diff --git a/tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.gyp b/tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.gyp new file mode 100644 index 00000000000000..b49fb591137bae --- /dev/null +++ b/tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.gyp @@ -0,0 +1,18 @@ +# 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. + +{ + 'includes': [ + '../../symroot.gypi', + ], + 'targets': [ + { + 'target_name': 'prog3', + 'type': 'executable', + 'sources': [ + 'prog3.c', + ], + }, + ], +} diff --git a/tools/gyp/test/subdirectory/src/symroot.gypi b/tools/gyp/test/subdirectory/src/symroot.gypi new file mode 100644 index 00000000000000..519916427c9f13 --- /dev/null +++ b/tools/gyp/test/subdirectory/src/symroot.gypi @@ -0,0 +1,16 @@ +# 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. + +{ + 'variables': { + 'set_symroot%': 0, + }, + 'conditions': [ + ['set_symroot == 1', { + 'xcode_settings': { + 'SYMROOT': '<(DEPTH)/build', + }, + }], + ], +} diff --git a/tools/gyp/test/symlinks/gyptest-symlinks.py b/tools/gyp/test/symlinks/gyptest-symlinks.py new file mode 100644 index 00000000000000..278818a992eedd --- /dev/null +++ b/tools/gyp/test/symlinks/gyptest-symlinks.py @@ -0,0 +1,66 @@ +#!/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. + +""" +Test that RelativePath(s, d) doesn't return a path starting with '..' when +s is textually below d, but is also a symlink to a file that is not below d. + +Returning .. in this case would break the Ninja generator in such a case, +because it computes output directories by concatenating paths, and concat'ing +a path starting with .. can unexpectedly erase other parts of the path. It's +difficult to test this directly since the test harness assumes toplevel_dir is +the root of the repository, but this test should at least verify that the +required behavior doesn't change. +""" + +import TestGyp +import os +import sys +import tempfile + +if sys.platform != 'win32': + test = TestGyp.TestGyp() + + # Copy hello.gyp and hello.c to temporary named files, which will then be + # symlinked back and processed. Note that we don't ask gyp to touch the + # original files at all; they are only there as source material for the copy. + # That's why hello.gyp references symlink_hello.c instead of hello.c. + with tempfile.NamedTemporaryFile(mode='w+') as gyp_file: + with tempfile.NamedTemporaryFile(mode='w+') as c_file: + with open('hello.gyp') as orig_gyp_file: + gyp_file.write(orig_gyp_file.read()) + gyp_file.flush() + with open('hello.c') as orig_c_file: + c_file.write(orig_c_file.read()) + c_file.flush() + # We need to flush the files because we want to read them before closing + # them, since when they are closed they will be deleted. + + # Don't proceed with the test on a system that doesn't let you read from + # a still-open temporary file. + if os.path.getsize(gyp_file.name) == 0: + raise OSError("Copy to temporary file didn't work.") + + symlink_gyp = test.built_file_path('symlink_hello.gyp') + symlink_c = test.built_file_path('symlink_hello.c') + outdir = os.path.dirname(symlink_gyp) + + # Make sure the outdir exists. + try: + os.makedirs(outdir) + except OSError: + if not os.path.isdir(outdir): + raise + os.symlink(gyp_file.name, symlink_gyp) + os.symlink(c_file.name, symlink_c) + + # Run gyp on the symlinked files. + test.run_gyp(symlink_gyp, chdir=outdir) + test.build(symlink_gyp, chdir=outdir) + test.run_built_executable('symlink_hello', stdout="Hello, world!\n", + chdir=outdir) + + test.pass_test() diff --git a/tools/gyp/test/symlinks/hello.c b/tools/gyp/test/symlinks/hello.c new file mode 100644 index 00000000000000..c63204b9485a27 --- /dev/null +++ b/tools/gyp/test/symlinks/hello.c @@ -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. +*/ + +#include + +int main(void) +{ + printf("Hello, world!\n"); + return 0; +} diff --git a/tools/gyp/test/symlinks/hello.gyp b/tools/gyp/test/symlinks/hello.gyp new file mode 100644 index 00000000000000..81d9f18e09521e --- /dev/null +++ b/tools/gyp/test/symlinks/hello.gyp @@ -0,0 +1,15 @@ +# 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': 'symlink_hello', + 'type': 'executable', + 'sources': [ + 'symlink_hello.c', + ], + }, + ], +} diff --git a/tools/gyp/test/target/gyptest-target.py b/tools/gyp/test/target/gyptest-target.py new file mode 100644 index 00000000000000..4338db739c2d26 --- /dev/null +++ b/tools/gyp/test/target/gyptest-target.py @@ -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 --git a/tools/gyp/test/target/hello.c b/tools/gyp/test/target/hello.c new file mode 100644 index 00000000000000..3d535d3ec6dd38 --- /dev/null +++ b/tools/gyp/test/target/hello.c @@ -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 --git a/tools/gyp/test/target/target.gyp b/tools/gyp/test/target/target.gyp new file mode 100644 index 00000000000000..c87e30f533c6d0 --- /dev/null +++ b/tools/gyp/test/target/target.gyp @@ -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 --git a/tools/gyp/test/toolsets/gyptest-toolsets.py b/tools/gyp/test/toolsets/gyptest-toolsets.py new file mode 100644 index 00000000000000..f80fce70a2d0ab --- /dev/null +++ b/tools/gyp/test/toolsets/gyptest-toolsets.py @@ -0,0 +1,31 @@ +#!/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 that toolsets are correctly applied +""" +import os +import sys +import TestGyp + +if sys.platform.startswith('linux'): + + test = TestGyp.TestGyp(formats=['make', 'ninja']) + + oldenv = os.environ.copy() + try: + os.environ['GYP_CROSSCOMPILE'] = '1' + test.run_gyp('toolsets.gyp') + finally: + os.environ.clear() + os.environ.update(oldenv) + + test.build('toolsets.gyp', test.ALL) + + test.run_built_executable('host-main', stdout="Host\nShared: Host\n") + test.run_built_executable('target-main', stdout="Target\nShared: Target\n") + + test.pass_test() diff --git a/tools/gyp/test/toolsets/main.cc b/tools/gyp/test/toolsets/main.cc new file mode 100644 index 00000000000000..bc47da99787096 --- /dev/null +++ b/tools/gyp/test/toolsets/main.cc @@ -0,0 +1,13 @@ +/* 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. */ + +#include + +const char *GetToolset(); +const char *GetToolsetShared(); + +int main(void) { + printf("%s\n", GetToolset()); + printf("Shared: %s\n", GetToolsetShared()); +} diff --git a/tools/gyp/test/toolsets/toolsets.cc b/tools/gyp/test/toolsets/toolsets.cc new file mode 100644 index 00000000000000..a45fa029cb7c03 --- /dev/null +++ b/tools/gyp/test/toolsets/toolsets.cc @@ -0,0 +1,11 @@ +/* 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. */ + +const char *GetToolset() { +#ifdef TARGET + return "Target"; +#else + return "Host"; +#endif +} diff --git a/tools/gyp/test/toolsets/toolsets.gyp b/tools/gyp/test/toolsets/toolsets.gyp new file mode 100644 index 00000000000000..3bc3a784ea8881 --- /dev/null +++ b/tools/gyp/test/toolsets/toolsets.gyp @@ -0,0 +1,62 @@ +# 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. + +{ + 'target_defaults': { + 'target_conditions': [ + ['_toolset=="target"', {'defines': ['TARGET']}] + ] + }, + 'targets': [ + { + 'target_name': 'toolsets', + 'type': 'static_library', + 'toolsets': ['target', 'host'], + 'sources': [ + 'toolsets.cc', + ], + }, + { + 'target_name': 'host-main', + 'type': 'executable', + 'toolsets': ['host'], + 'dependencies': ['toolsets', 'toolsets_shared'], + 'sources': [ + 'main.cc', + ], + }, + { + 'target_name': 'target-main', + 'type': 'executable', + 'dependencies': ['toolsets', 'toolsets_shared'], + 'sources': [ + 'main.cc', + ], + }, + # This tests that build systems can handle a shared library being build for + # both host and target. + { + 'target_name': 'janus', + 'type': 'shared_library', + 'toolsets': ['target', 'host'], + 'sources': [ + 'toolsets.cc', + ], + 'cflags': [ '-fPIC' ], + }, + { + 'target_name': 'toolsets_shared', + 'type': 'shared_library', + 'toolsets': ['target', 'host'], + 'target_conditions': [ + # Ensure target and host have different shared_library names + ['_toolset=="host"', {'product_extension': 'host'}], + ], + 'sources': [ + 'toolsets_shared.cc', + ], + 'cflags': [ '-fPIC' ], + }, + ], +} diff --git a/tools/gyp/test/toolsets/toolsets_shared.cc b/tools/gyp/test/toolsets/toolsets_shared.cc new file mode 100644 index 00000000000000..794af2c0bd69e9 --- /dev/null +++ b/tools/gyp/test/toolsets/toolsets_shared.cc @@ -0,0 +1,11 @@ +/* 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. */ + +const char *GetToolsetShared() { +#ifdef TARGET + return "Target"; +#else + return "Host"; +#endif +} diff --git a/tools/gyp/test/toplevel-dir/gyptest-toplevel-dir.py b/tools/gyp/test/toplevel-dir/gyptest-toplevel-dir.py new file mode 100644 index 00000000000000..9e69512dd36cc1 --- /dev/null +++ b/tools/gyp/test/toplevel-dir/gyptest-toplevel-dir.py @@ -0,0 +1,31 @@ +#!/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 building a subsidiary dependent target from a .gyp file in a +subdirectory, without specifying an explicit output build directory, +and using the subdirectory's solution or project file as the entry point. +""" + +import TestGyp +import errno + +test = TestGyp.TestGyp(formats=['ninja', 'make']) + +# We want our Makefile to be one dir up from main.gyp. +test.run_gyp('main.gyp', '--toplevel-dir=..', chdir='src/sub1') + +toplevel_dir = 'src' + +test.build('sub1/main.gyp', test.ALL, chdir=toplevel_dir) + +test.built_file_must_exist('prog1', type=test.EXECUTABLE, chdir=toplevel_dir) + +test.run_built_executable('prog1', + chdir=toplevel_dir, + stdout="Hello from prog1.c\n") + +test.pass_test() diff --git a/tools/gyp/test/toplevel-dir/src/sub1/main.gyp b/tools/gyp/test/toplevel-dir/src/sub1/main.gyp new file mode 100644 index 00000000000000..33219010e48dac --- /dev/null +++ b/tools/gyp/test/toplevel-dir/src/sub1/main.gyp @@ -0,0 +1,18 @@ +# 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': 'prog1', + 'type': 'executable', + 'dependencies': [ + '<(DEPTH)/../sub2/prog2.gyp:prog2', + ], + 'sources': [ + 'prog1.c', + ], + }, + ], +} diff --git a/tools/gyp/test/toplevel-dir/src/sub1/prog1.c b/tools/gyp/test/toplevel-dir/src/sub1/prog1.c new file mode 100644 index 00000000000000..218e99401cb259 --- /dev/null +++ b/tools/gyp/test/toplevel-dir/src/sub1/prog1.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + printf("Hello from prog1.c\n"); + return 0; +} diff --git a/tools/gyp/test/toplevel-dir/src/sub2/prog2.c b/tools/gyp/test/toplevel-dir/src/sub2/prog2.c new file mode 100644 index 00000000000000..12a31883b93a99 --- /dev/null +++ b/tools/gyp/test/toplevel-dir/src/sub2/prog2.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + printf("Hello from prog2.c\n"); + return 0; +} diff --git a/tools/gyp/test/toplevel-dir/src/sub2/prog2.gyp b/tools/gyp/test/toplevel-dir/src/sub2/prog2.gyp new file mode 100644 index 00000000000000..59345483692b6c --- /dev/null +++ b/tools/gyp/test/toplevel-dir/src/sub2/prog2.gyp @@ -0,0 +1,15 @@ +# 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': 'prog2', + 'type': 'executable', + 'sources': [ + 'prog2.c', + ], + }, + ], +} diff --git a/tools/gyp/test/variables/commands/commands-repeated.gyp b/tools/gyp/test/variables/commands/commands-repeated.gyp new file mode 100644 index 00000000000000..1b4b644119a04c --- /dev/null +++ b/tools/gyp/test/variables/commands/commands-repeated.gyp @@ -0,0 +1,129 @@ +# 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. + +# This is a simple test file to make sure that variable substitution +# happens correctly. Run "run_tests.py" using python to generate the +# output from this gyp file. + +# noinspection Duplicates +{ + 'variables': { + 'pi': 'import math; print(\'%.15f\' % math.pi)', + 'third_letters': "<(other_letters)HIJK", + 'letters_list': 'ABCD', + 'other_letters': '<(letters_list)EFG', + 'check_included': '<(included_variable)', + 'check_lists': [ + '<(included_variable)', + '<(third_letters)', + ], + 'check_int': 5, + 'check_str_int': '6', + 'check_list_int': [ + 7, + '8', + 9, + ], + 'not_int_1': ' 10', + 'not_int_2': '11 ', + 'not_int_3': '012', + 'not_int_4': '13.0', + 'not_int_5': '+14', + 'negative_int': '-15', + 'zero_int': '0', + }, + 'includes': [ + 'commands.gypi', + ], + 'targets': [ + { + 'target_name': 'foo', + 'type': 'none', + 'variables': { + 'var1': ' commands.gyp.stdout +python ../../../gyp_main.py --ignore-environment --debug variables --format gypd --depth . commands.gyp > commands.gyp.ignore-env.stdout +cp -f commands.gypd commands.gypd.golden +python ../../../gyp_main.py --debug variables --format gypd --depth . commands-repeated.gyp > commands-repeated.gyp.stdout +cp -f commands-repeated.gypd commands-repeated.gypd.golden diff --git a/tools/gyp/test/variables/empty/empty.gyp b/tools/gyp/test/variables/empty/empty.gyp new file mode 100644 index 00000000000000..207be06fe710ed --- /dev/null +++ b/tools/gyp/test/variables/empty/empty.gyp @@ -0,0 +1,13 @@ +# 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. + +{ + 'includes': ['empty.gypi'], + 'targets': [ + { + 'target_name': 'empty', + 'type': 'none', + }, + ], +} diff --git a/tools/gyp/test/variables/empty/empty.gypi b/tools/gyp/test/variables/empty/empty.gypi new file mode 100644 index 00000000000000..e95031fca59b6c --- /dev/null +++ b/tools/gyp/test/variables/empty/empty.gypi @@ -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. + +{ + 'variables': { + '': '', + }, +} diff --git a/tools/gyp/test/variables/empty/gyptest-empty.py b/tools/gyp/test/variables/empty/gyptest-empty.py new file mode 100644 index 00000000000000..4cbe166fdc3624 --- /dev/null +++ b/tools/gyp/test/variables/empty/gyptest-empty.py @@ -0,0 +1,19 @@ +#!/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. + +""" +Test that empty variable names don't cause infinite loops. +""" + +import os + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('empty.gyp') + +test.pass_test() diff --git a/tools/gyp/test/variables/filelist/filelist.gyp.stdout b/tools/gyp/test/variables/filelist/filelist.gyp.stdout new file mode 100644 index 00000000000000..595a19c68483ce --- /dev/null +++ b/tools/gyp/test/variables/filelist/filelist.gyp.stdout @@ -0,0 +1,26 @@ +VARIABLES:input.py:562:ExpandVariables Matches: {'content': 'names.txt <@(names', 'is_array': '', 'replace': '<|(names.txt <@(names)', 'type': '<|', 'command_string': None} +VARIABLES:input.py:562:ExpandVariables Matches: {'content': 'names', 'is_array': '', 'replace': '<@(names)', 'type': '<@', 'command_string': None} +VARIABLES:input.py:797:ExpandVariables Found output 'names.txt John Jacob Jingleheimer Schmidt', recursing. +VARIABLES:input.py:797:ExpandVariables Found output 'names.txt', recursing. +VARIABLES:input.py:562:ExpandVariables Matches: {'content': 'names_listfile', 'is_array': '', 'replace': '<(names_listfile)', 'type': '<', 'command_string': None} +VARIABLES:input.py:797:ExpandVariables Found output 'names.txt', recursing. +VARIABLES:input.py:562:ExpandVariables Matches: {'content': 'names_listfile', 'is_array': '', 'replace': '<(names_listfile)', 'type': '<', 'command_string': None} +VARIABLES:input.py:797:ExpandVariables Found output 'names.txt', recursing. +VARIABLES:input.py:562:ExpandVariables Matches: {'content': 'cat <(names_listfile', 'is_array': '', 'replace': ' filelist.gyp.stdout +cp -f src/filelist.gypd filelist.gypd.golden diff --git a/tools/gyp/test/variables/latelate/gyptest-latelate.py b/tools/gyp/test/variables/latelate/gyptest-latelate.py new file mode 100644 index 00000000000000..2d77dfec5e9b8d --- /dev/null +++ b/tools/gyp/test/variables/latelate/gyptest-latelate.py @@ -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. + +""" +Verifies that ^(latelate) style variables work. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('latelate.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('latelate.gyp', test.ALL, chdir='relocate/src') + +test.run_built_executable( + 'program', chdir='relocate/src', stdout='program.cc\n') + + +test.pass_test() diff --git a/tools/gyp/test/variables/latelate/src/latelate.gyp b/tools/gyp/test/variables/latelate/src/latelate.gyp new file mode 100644 index 00000000000000..312f3765b6744f --- /dev/null +++ b/tools/gyp/test/variables/latelate/src/latelate.gyp @@ -0,0 +1,34 @@ +# 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. + +{ + 'target_defaults': { + 'target_conditions': [ + ['has_lame==1', { + 'sources/': [ + ['exclude', 'lame'], + ], + }], + ], + }, + 'targets': [ + { + 'target_name': 'program', + 'type': 'executable', + 'variables': { + 'has_lame': 1, + }, + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + 'defines': [ + 'FOO="^(_sources)"', + ], + 'sources': [ + 'program.cc', + 'this_is_lame.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/variables/latelate/src/program.cc b/tools/gyp/test/variables/latelate/src/program.cc new file mode 100644 index 00000000000000..97c98ae5b9d834 --- /dev/null +++ b/tools/gyp/test/variables/latelate/src/program.cc @@ -0,0 +1,13 @@ +/* + * 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(void) { + printf(FOO "\n"); + return 0; +} diff --git a/tools/gyp/test/variables/variable-in-path/C1/hello.cc b/tools/gyp/test/variables/variable-in-path/C1/hello.cc new file mode 100644 index 00000000000000..1711567ef56670 --- /dev/null +++ b/tools/gyp/test/variables/variable-in-path/C1/hello.cc @@ -0,0 +1,7 @@ +// 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. + +int main() { + return 0; +} diff --git a/tools/gyp/test/variables/variable-in-path/gyptest-variable-in-path.py b/tools/gyp/test/variables/variable-in-path/gyptest-variable-in-path.py new file mode 100644 index 00000000000000..b73a279da737fc --- /dev/null +++ b/tools/gyp/test/variables/variable-in-path/gyptest-variable-in-path.py @@ -0,0 +1,23 @@ +#!/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. + +""" +Make sure <(CONFIGURATION_NAME) variable is correctly expanded. +""" + +import TestGyp + +import sys + +test = TestGyp.TestGyp() +test.set_configuration('C1') + +test.run_gyp('variable-in-path.gyp') +test.build('variable-in-path.gyp', 'hello1') +test.build('variable-in-path.gyp', 'hello2') + + +test.pass_test() diff --git a/tools/gyp/test/variables/variable-in-path/variable-in-path.gyp b/tools/gyp/test/variables/variable-in-path/variable-in-path.gyp new file mode 100644 index 00000000000000..908d21eb662908 --- /dev/null +++ b/tools/gyp/test/variables/variable-in-path/variable-in-path.gyp @@ -0,0 +1,31 @@ +# Copyright (c) 2010 Google 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', + 'type': 'executable', + 'sources': [ + '<(CONFIGURATION_NAME)/hello.cc', + ], + }, + { + 'target_name': 'hello2', + 'type': 'executable', + 'sources': [ + './<(CONFIGURATION_NAME)/hello.cc', + ], + }, + ], + 'target_defaults': { + 'default_configuration': 'C1', + 'configurations': { + 'C1': { + }, + 'C2': { + }, + }, + }, +} diff --git a/tools/gyp/test/win/asm-files/asm-files.gyp b/tools/gyp/test/win/asm-files/asm-files.gyp new file mode 100644 index 00000000000000..b1f132ceea70a5 --- /dev/null +++ b/tools/gyp/test/win/asm-files/asm-files.gyp @@ -0,0 +1,17 @@ +# 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': 'sources_with_asm', + 'type': 'executable', + 'sources': [ + 'hello.cc', + 'b.s', + 'c.S', + ], + }, + ] +} diff --git a/tools/gyp/test/win/asm-files/b.s b/tools/gyp/test/win/asm-files/b.s new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/win/asm-files/c.S b/tools/gyp/test/win/asm-files/c.S new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/win/asm-files/hello.cc b/tools/gyp/test/win/asm-files/hello.cc new file mode 100644 index 00000000000000..1711567ef56670 --- /dev/null +++ b/tools/gyp/test/win/asm-files/hello.cc @@ -0,0 +1,7 @@ +// 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. + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/batch-file-action/batch-file-action.gyp b/tools/gyp/test/win/batch-file-action/batch-file-action.gyp new file mode 100644 index 00000000000000..e4db9af9d3d6c9 --- /dev/null +++ b/tools/gyp/test/win/batch-file-action/batch-file-action.gyp @@ -0,0 +1,21 @@ +# 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_batch', + 'type': 'none', + 'actions': [ + { + 'action_name': 'copy_to_output', + 'inputs': ['infile'], + 'outputs': ['outfile'], + 'action': ['somecmd.bat', 'infile', 'outfile'], + 'msvs_cygwin_shell': 0, + } + ], + }, + ] +} diff --git a/tools/gyp/test/win/batch-file-action/infile b/tools/gyp/test/win/batch-file-action/infile new file mode 100644 index 00000000000000..3f9177e45e805c --- /dev/null +++ b/tools/gyp/test/win/batch-file-action/infile @@ -0,0 +1 @@ +input diff --git a/tools/gyp/test/win/batch-file-action/somecmd.bat b/tools/gyp/test/win/batch-file-action/somecmd.bat new file mode 100644 index 00000000000000..3b5ae80a42cca8 --- /dev/null +++ b/tools/gyp/test/win/batch-file-action/somecmd.bat @@ -0,0 +1,5 @@ +@echo off +:: The redirs to nul are important. %2 can end up being an unterminated "'d +:: string, so the remainder of the command line becomes the target file name, +:: which in turn fails because it's a filename containing >, nul, etc. +copy /y %1 %2 >nul 2>nul diff --git a/tools/gyp/test/win/command-quote/a.S b/tools/gyp/test/win/command-quote/a.S new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/win/command-quote/bat with spaces.bat b/tools/gyp/test/win/command-quote/bat with spaces.bat new file mode 100644 index 00000000000000..dc3508f9a9e062 --- /dev/null +++ b/tools/gyp/test/win/command-quote/bat with spaces.bat @@ -0,0 +1,7 @@ +@echo off + +:: 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. + +copy %1 %2 diff --git a/tools/gyp/test/win/command-quote/command-quote.gyp b/tools/gyp/test/win/command-quote/command-quote.gyp new file mode 100644 index 00000000000000..faf724674fc8a5 --- /dev/null +++ b/tools/gyp/test/win/command-quote/command-quote.gyp @@ -0,0 +1,79 @@ +# 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. + +{ + 'target_defaults': { + 'msvs_cygwin_dirs': ['../../../../../<(DEPTH)/third_party/cygwin'], + }, + 'targets': [ + { + 'target_name': 'test_batch', + 'type': 'none', + 'rules': [ + { + 'rule_name': 'build_with_batch', + 'msvs_cygwin_shell': 0, + 'extension': 'S', + 'outputs': ['output.obj'], + 'action': ['call go.bat', '<(RULE_INPUT_PATH)', 'output.obj'], + },], + 'sources': ['a.S'], + }, + { + 'target_name': 'test_call_separate', + 'type': 'none', + 'rules': [ + { + 'rule_name': 'build_with_batch2', + 'msvs_cygwin_shell': 0, + 'extension': 'S', + 'outputs': ['output2.obj'], + 'action': ['call', 'go.bat', '<(RULE_INPUT_PATH)', 'output2.obj'], + },], + 'sources': ['a.S'], + }, + { + 'target_name': 'test_with_spaces', + 'type': 'none', + 'rules': [ + { + 'rule_name': 'build_with_batch3', + 'msvs_cygwin_shell': 0, + 'extension': 'S', + 'outputs': ['output3.obj'], + 'action': ['bat with spaces.bat', '<(RULE_INPUT_PATH)', 'output3.obj'], + },], + 'sources': ['a.S'], + }, + { + 'target_name': 'test_with_double_quotes', + 'type': 'none', + 'rules': [ + { + 'rule_name': 'build_with_batch3', + 'msvs_cygwin_shell': 1, + 'extension': 'S', + 'outputs': ['output4.obj'], + 'arguments': ['-v'], + 'action': ['python', '-c', 'import shutil; ' + 'shutil.copy("<(RULE_INPUT_PATH)", "output4.obj")'], + },], + 'sources': ['a.S'], + }, + { + 'target_name': 'test_with_single_quotes', + 'type': 'none', + 'rules': [ + { + 'rule_name': 'build_with_batch3', + 'msvs_cygwin_shell': 1, + 'extension': 'S', + 'outputs': ['output5.obj'], + 'action': ['python', '-c', "import shutil; " + "shutil.copy('<(RULE_INPUT_PATH)', 'output5.obj')"], + },], + 'sources': ['a.S'], + }, + ] +} diff --git a/tools/gyp/test/win/command-quote/go.bat b/tools/gyp/test/win/command-quote/go.bat new file mode 100644 index 00000000000000..dc3508f9a9e062 --- /dev/null +++ b/tools/gyp/test/win/command-quote/go.bat @@ -0,0 +1,7 @@ +@echo off + +:: 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. + +copy %1 %2 diff --git a/tools/gyp/test/win/command-quote/subdir/and/another/in-subdir.gyp b/tools/gyp/test/win/command-quote/subdir/and/another/in-subdir.gyp new file mode 100644 index 00000000000000..3dff4c40b9781a --- /dev/null +++ b/tools/gyp/test/win/command-quote/subdir/and/another/in-subdir.gyp @@ -0,0 +1,27 @@ +# 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_batch_depth', + 'type': 'none', + 'variables': { + # Taken from native_client/build/common.gypi. Seems unintentional (a + # string in a 1 element list)? But since it works on other generators, + # I guess it should work here too. + 'filepath': [ 'call <(DEPTH)/../../../go.bat' ], + }, + 'rules': [ + { + 'rule_name': 'build_with_batch4', + 'msvs_cygwin_shell': 0, + 'extension': 'S', + 'outputs': ['output4.obj'], + 'action': ['<@(filepath)', '<(RULE_INPUT_PATH)', 'output4.obj'], + },], + 'sources': ['<(DEPTH)\\..\\..\\..\\a.S'], + }, + ] +} diff --git a/tools/gyp/test/win/compiler-flags/additional-include-dirs.cc b/tools/gyp/test/win/compiler-flags/additional-include-dirs.cc new file mode 100644 index 00000000000000..f1e11dd12d6d7f --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/additional-include-dirs.cc @@ -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. + +// No path qualification to test compiler include dir specification. +#include "header.h" + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/additional-include-dirs.gyp b/tools/gyp/test/win/compiler-flags/additional-include-dirs.gyp new file mode 100644 index 00000000000000..42c7e849f63b4c --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/additional-include-dirs.gyp @@ -0,0 +1,20 @@ +# 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_incs', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'AdditionalIncludeDirectories': [ + 'subdir', + ], + } + }, + 'sources': ['additional-include-dirs.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/compiler-flags/additional-options.cc b/tools/gyp/test/win/compiler-flags/additional-options.cc new file mode 100644 index 00000000000000..c79572bafad3cb --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/additional-options.cc @@ -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. + +int main() { + // Generate a warning that will appear at level 4, but not level 1 + // (truncation and unused local). + char c = 123456; + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/additional-options.gyp b/tools/gyp/test/win/compiler-flags/additional-options.gyp new file mode 100644 index 00000000000000..6a365a2062aed5 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/additional-options.gyp @@ -0,0 +1,31 @@ +# 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_additional_none', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarningLevel': '4', + 'WarnAsError': 'true', + } + }, + 'sources': ['additional-options.cc'], + }, + { + 'target_name': 'test_additional_one', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarningLevel': '4', + 'WarnAsError': 'true', + 'AdditionalOptions': [ '/W1' ], + } + }, + 'sources': ['additional-options.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/compiler-flags/analysis.gyp b/tools/gyp/test/win/compiler-flags/analysis.gyp new file mode 100644 index 00000000000000..97e942258fbaca --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/analysis.gyp @@ -0,0 +1,40 @@ +# 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_analysis_on', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnablePREfast': 'true', + 'WarnAsError': 'true', + }, + }, + 'sources': ['uninit.cc'], + }, + { + 'target_name': 'test_analysis_off', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnablePREfast': 'false', + 'WarnAsError': 'true', + }, + }, + 'sources': ['uninit.cc'], + }, + { + 'target_name': 'test_analysis_unspec', + 'type': 'executable', + 'sources': ['uninit.cc'], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarnAsError': 'true', + }, + }, + }, + ] +} diff --git a/tools/gyp/test/win/compiler-flags/buffer-security-check.gyp b/tools/gyp/test/win/compiler-flags/buffer-security-check.gyp new file mode 100644 index 00000000000000..cc5a12b9536788 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/buffer-security-check.gyp @@ -0,0 +1,51 @@ +# 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': [ + # Turn debug information on so that we can see the name of the buffer + # security check cookie in the disassembly. + { + 'target_name': 'test_bsc_unset', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + }, + }, + 'sources': ['buffer-security.cc'], + }, + { + 'target_name': 'test_bsc_off', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'BufferSecurityCheck': 'false', + 'DebugInformationFormat': '3', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + }, + }, + 'sources': ['buffer-security.cc'], + }, + { + 'target_name': 'test_bsc_on', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'BufferSecurityCheck': 'true', + 'DebugInformationFormat': '3', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + }, + }, + 'sources': ['buffer-security.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/compiler-flags/buffer-security.cc b/tools/gyp/test/win/compiler-flags/buffer-security.cc new file mode 100644 index 00000000000000..e8a48a2a6741fc --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/buffer-security.cc @@ -0,0 +1,12 @@ +// 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 +#include + +int main() { + char* stuff = reinterpret_cast(_alloca(256)); + strcpy(stuff, "blah"); + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/calling-convention-cdecl.def b/tools/gyp/test/win/compiler-flags/calling-convention-cdecl.def new file mode 100644 index 00000000000000..dc1dba055ac3c5 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/calling-convention-cdecl.def @@ -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 --git a/tools/gyp/test/win/compiler-flags/calling-convention-fastcall.def b/tools/gyp/test/win/compiler-flags/calling-convention-fastcall.def new file mode 100644 index 00000000000000..2c61afe208a4d7 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/calling-convention-fastcall.def @@ -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 --git a/tools/gyp/test/win/compiler-flags/calling-convention-stdcall.def b/tools/gyp/test/win/compiler-flags/calling-convention-stdcall.def new file mode 100644 index 00000000000000..6c7e05e9ea6f4b --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/calling-convention-stdcall.def @@ -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 --git a/tools/gyp/test/win/compiler-flags/calling-convention-vectorcall.def b/tools/gyp/test/win/compiler-flags/calling-convention-vectorcall.def new file mode 100644 index 00000000000000..4ef119c3e37a1c --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/calling-convention-vectorcall.def @@ -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 --git a/tools/gyp/test/win/compiler-flags/calling-convention.cc b/tools/gyp/test/win/compiler-flags/calling-convention.cc new file mode 100644 index 00000000000000..0d78a0cc05a251 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/calling-convention.cc @@ -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 --git a/tools/gyp/test/win/compiler-flags/calling-convention.gyp b/tools/gyp/test/win/compiler-flags/calling-convention.gyp new file mode 100644 index 00000000000000..5069c552bceb85 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/calling-convention.gyp @@ -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 --git a/tools/gyp/test/win/compiler-flags/character-set-mbcs.cc b/tools/gyp/test/win/compiler-flags/character-set-mbcs.cc new file mode 100644 index 00000000000000..3286304730d394 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/character-set-mbcs.cc @@ -0,0 +1,11 @@ +// 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. + +#ifndef _MBCS +#error +#endif + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/character-set-unicode.cc b/tools/gyp/test/win/compiler-flags/character-set-unicode.cc new file mode 100644 index 00000000000000..32e69724a5097f --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/character-set-unicode.cc @@ -0,0 +1,15 @@ +// 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. + +#ifndef _UNICODE +#error +#endif + +#ifndef UNICODE +#error +#endif + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/character-set.gyp b/tools/gyp/test/win/compiler-flags/character-set.gyp new file mode 100644 index 00000000000000..3dc45557d9ba68 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/character-set.gyp @@ -0,0 +1,35 @@ +# 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_cs_notset', + 'product_name': 'test_cs_notset', + 'type': 'executable', + 'msvs_configuration_attributes': { + 'CharacterSet': '0' + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_cs_unicode', + 'product_name': 'test_cs_unicode', + 'type': 'executable', + 'msvs_configuration_attributes': { + 'CharacterSet': '1' + }, + 'sources': ['character-set-unicode.cc'], + }, + { + 'target_name': 'test_cs_mbcs', + 'product_name': 'test_cs_mbcs', + 'type': 'executable', + 'msvs_configuration_attributes': { + 'CharacterSet': '2' + }, + 'sources': ['character-set-mbcs.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/compiler-flags/compile-as-managed.cc b/tools/gyp/test/win/compiler-flags/compile-as-managed.cc new file mode 100644 index 00000000000000..a29c71ee1da9c1 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/compile-as-managed.cc @@ -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 --git a/tools/gyp/test/win/compiler-flags/compile-as-managed.gyp b/tools/gyp/test/win/compiler-flags/compile-as-managed.gyp new file mode 100644 index 00000000000000..3bacbbc135e63b --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/compile-as-managed.gyp @@ -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 --git a/tools/gyp/test/win/compiler-flags/compile-as-winrt.cc b/tools/gyp/test/win/compiler-flags/compile-as-winrt.cc new file mode 100644 index 00000000000000..da9954f8fbce0a --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/compile-as-winrt.cc @@ -0,0 +1,12 @@ +// Copyright (c) 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +using namespace Platform; + +int main() { + wchar_t msg[] = L"Test"; + String^ str1 = ref new String(msg); + auto str2 = String::Concat(str1, " Concat"); + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/compile-as-winrt.gyp b/tools/gyp/test/win/compiler-flags/compile-as-winrt.gyp new file mode 100644 index 00000000000000..8978e5059de2f2 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/compile-as-winrt.gyp @@ -0,0 +1,20 @@ +# Copyright (c) 2016 Google 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-winrt', + 'type': 'executable', + 'msvs_windows_sdk_version': 'v10.0', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'AdditionalUsingDirectories': ['$(VCInstallDir)vcpackages;$(WindowsSdkDir)UnionMetadata;%(AdditionalUsingDirectories)'], + 'CompileAsWinRT': 'true' + } + }, + 'sources': ['compile-as-winrt.cc'] + } + ] +} diff --git a/tools/gyp/test/win/compiler-flags/debug-format.gyp b/tools/gyp/test/win/compiler-flags/debug-format.gyp new file mode 100644 index 00000000000000..daaed23ff1f7c0 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/debug-format.gyp @@ -0,0 +1,48 @@ +# 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-debug-format-off', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '0' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test-debug-format-oldstyle', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '1' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test-debug-format-pdb', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test-debug-format-editcontinue', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '4' + } + }, + 'sources': ['hello.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/compiler-flags/default-char-is-unsigned.cc b/tools/gyp/test/win/compiler-flags/default-char-is-unsigned.cc new file mode 100644 index 00000000000000..beeca2aa156f1a --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/default-char-is-unsigned.cc @@ -0,0 +1,15 @@ +// 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. + +template +struct CompileAssert { +}; + +#define COMPILE_ASSERT(expr, msg) \ + typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] + +int main() { + COMPILE_ASSERT(char(-1) > 0, default_char_is_unsigned); + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/default-char-is-unsigned.gyp b/tools/gyp/test/win/compiler-flags/default-char-is-unsigned.gyp new file mode 100644 index 00000000000000..941e5810dd1d06 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/default-char-is-unsigned.gyp @@ -0,0 +1,20 @@ +# Copyright (c) 2010 Google 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_char_is_unsigned', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DefaultCharIsUnsigned': 'true', + }, + }, + 'sources': [ + 'default-char-is-unsigned.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/win/compiler-flags/disable-specific-warnings.cc b/tools/gyp/test/win/compiler-flags/disable-specific-warnings.cc new file mode 100644 index 00000000000000..d312f5f48121a1 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/disable-specific-warnings.cc @@ -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 --git a/tools/gyp/test/win/compiler-flags/disable-specific-warnings.gyp b/tools/gyp/test/win/compiler-flags/disable-specific-warnings.gyp new file mode 100644 index 00000000000000..d81d694c620107 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/disable-specific-warnings.gyp @@ -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 --git a/tools/gyp/test/win/compiler-flags/enable-enhanced-instruction-set.cc b/tools/gyp/test/win/compiler-flags/enable-enhanced-instruction-set.cc new file mode 100644 index 00000000000000..432ef54eda2be5 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/enable-enhanced-instruction-set.cc @@ -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 --git a/tools/gyp/test/win/compiler-flags/enable-enhanced-instruction-set.gyp b/tools/gyp/test/win/compiler-flags/enable-enhanced-instruction-set.gyp new file mode 100644 index 00000000000000..9c49edc7ffc89c --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/enable-enhanced-instruction-set.gyp @@ -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 --git a/tools/gyp/test/win/compiler-flags/exception-handling-on.cc b/tools/gyp/test/win/compiler-flags/exception-handling-on.cc new file mode 100644 index 00000000000000..5d9a3af77ded07 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/exception-handling-on.cc @@ -0,0 +1,24 @@ +// 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 +#include + +void fail() { + try { + int i = 0, j = 1; + j /= i; + } catch(...) { + exit(1); + } +} + +int main() { + __try { + fail(); + } __except(EXCEPTION_EXECUTE_HANDLER) { + return 2; + } + return 3; +} diff --git a/tools/gyp/test/win/compiler-flags/exception-handling.gyp b/tools/gyp/test/win/compiler-flags/exception-handling.gyp new file mode 100644 index 00000000000000..c266768ddae5f3 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/exception-handling.gyp @@ -0,0 +1,46 @@ +# 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': [ + # Optimization disabled so that the exception-causing code is not removed + # (divide by zero was getting optimized away in VS2010). + { + 'target_name': 'test_eh_off', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'ExceptionHandling': '0', + 'WarnAsError': 'true', + 'Optimization': '0', + } + }, + 'sources': ['exception-handling-on.cc'], + }, + { + 'target_name': 'test_eh_s', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'ExceptionHandling': '1', + 'WarnAsError': 'true', + 'Optimization': '0', + } + }, + 'sources': ['exception-handling-on.cc'], + }, + { + 'target_name': 'test_eh_a', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'ExceptionHandling': '2', + 'WarnAsError': 'true', + 'Optimization': '0', + } + }, + 'sources': ['exception-handling-on.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/compiler-flags/floating-point-model-fast.cc b/tools/gyp/test/win/compiler-flags/floating-point-model-fast.cc new file mode 100644 index 00000000000000..9d22152f5e5fcd --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/floating-point-model-fast.cc @@ -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 --git a/tools/gyp/test/win/compiler-flags/floating-point-model-precise.cc b/tools/gyp/test/win/compiler-flags/floating-point-model-precise.cc new file mode 100644 index 00000000000000..1191a74ed1a633 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/floating-point-model-precise.cc @@ -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 --git a/tools/gyp/test/win/compiler-flags/floating-point-model-strict.cc b/tools/gyp/test/win/compiler-flags/floating-point-model-strict.cc new file mode 100644 index 00000000000000..1ffde36e0c5b08 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/floating-point-model-strict.cc @@ -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 --git a/tools/gyp/test/win/compiler-flags/floating-point-model.gyp b/tools/gyp/test/win/compiler-flags/floating-point-model.gyp new file mode 100644 index 00000000000000..857b275a8f9957 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/floating-point-model.gyp @@ -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 --git a/tools/gyp/test/win/compiler-flags/force-include-files-with-precompiled.cc b/tools/gyp/test/win/compiler-flags/force-include-files-with-precompiled.cc new file mode 100644 index 00000000000000..85cb0f32a6f304 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/force-include-files-with-precompiled.cc @@ -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 --git a/tools/gyp/test/win/compiler-flags/force-include-files.cc b/tools/gyp/test/win/compiler-flags/force-include-files.cc new file mode 100644 index 00000000000000..4a93de55d4ebfa --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/force-include-files.cc @@ -0,0 +1,8 @@ +// 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. + +int main() { + std::list > l; + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/force-include-files.gyp b/tools/gyp/test/win/compiler-flags/force-include-files.gyp new file mode 100644 index 00000000000000..2031546cc57d6d --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/force-include-files.gyp @@ -0,0 +1,36 @@ +# Copyright (c) 2010 Google 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_include_files', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'ForcedIncludeFiles': ['string', 'vector', 'list'], + }, + }, + 'sources': [ + '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 --git a/tools/gyp/test/win/compiler-flags/function-level-linking.cc b/tools/gyp/test/win/compiler-flags/function-level-linking.cc new file mode 100644 index 00000000000000..49522728170d1a --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/function-level-linking.cc @@ -0,0 +1,11 @@ +// 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. + +int comdat_function() { + return 1; +} + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/function-level-linking.gyp b/tools/gyp/test/win/compiler-flags/function-level-linking.gyp new file mode 100644 index 00000000000000..5858586a249a71 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/function-level-linking.gyp @@ -0,0 +1,28 @@ +# 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_fll_off', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableFunctionLevelLinking': 'false' + } + }, + 'sources': ['function-level-linking.cc'], + }, + { + 'target_name': 'test_fll_on', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableFunctionLevelLinking': 'true', + } + }, + 'sources': ['function-level-linking.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/compiler-flags/hello.cc b/tools/gyp/test/win/compiler-flags/hello.cc new file mode 100644 index 00000000000000..1711567ef56670 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/hello.cc @@ -0,0 +1,7 @@ +// 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. + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/optimizations.gyp b/tools/gyp/test/win/compiler-flags/optimizations.gyp new file mode 100644 index 00000000000000..e63096f0f70f3f --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/optimizations.gyp @@ -0,0 +1,207 @@ +# 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_opt_off', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'Optimization': '0' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_lev_size', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'Optimization': '1' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_lev_speed', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'Optimization': '2' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_lev_max', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'Optimization': '3' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_unset', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_fpo', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'OmitFramePointers': 'true' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_fpo_off', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'OmitFramePointers': 'false' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_intrinsic', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableIntrinsicFunctions': 'true' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_intrinsic_off', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableIntrinsicFunctions': 'false' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_inline_off', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'InlineFunctionExpansion': '0' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_inline_manual', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'InlineFunctionExpansion': '1' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_inline_auto', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'InlineFunctionExpansion': '2' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_neither', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'FavorSizeOrSpeed': '0' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_speed', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'FavorSizeOrSpeed': '1' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_size', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'FavorSizeOrSpeed': '2' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_wpo', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WholeProgramOptimization': 'true' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_sp', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'StringPooling': 'true' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_sp_off', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'StringPooling': 'false' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_fso', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableFiberSafeOptimizations': 'true' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_opt_fso_off', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableFiberSafeOptimizations': 'false' + } + }, + 'sources': ['hello.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/compiler-flags/pdbname-override.gyp b/tools/gyp/test/win/compiler-flags/pdbname-override.gyp new file mode 100644 index 00000000000000..dad20e01fde236 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/pdbname-override.gyp @@ -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': 'test_pdbname', + 'type': 'executable', + 'sources': [ + 'hello.cc', + 'pdbname.cc', + ], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3', + 'ProgramDataBaseFileName': '<(PRODUCT_DIR)/compiler_generated.pdb', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'ProgramDatabaseFile': '<(PRODUCT_DIR)/linker_generated.pdb', + }, + }, + }, + ] +} diff --git a/tools/gyp/test/win/compiler-flags/pdbname.cc b/tools/gyp/test/win/compiler-flags/pdbname.cc new file mode 100644 index 00000000000000..0fe05d5afb095b --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/pdbname.cc @@ -0,0 +1,7 @@ +// 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. + +int some_function() { + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/pdbname.gyp b/tools/gyp/test/win/compiler-flags/pdbname.gyp new file mode 100644 index 00000000000000..8fcf754727c228 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/pdbname.gyp @@ -0,0 +1,24 @@ +# 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_pdbname', + 'type': 'executable', + 'sources': [ + 'hello.cc', + 'pdbname.cc', + ], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + }, + }, + }, + ] +} diff --git a/tools/gyp/test/win/compiler-flags/precomp.cc b/tools/gyp/test/win/compiler-flags/precomp.cc new file mode 100644 index 00000000000000..d16bac890fe92c --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/precomp.cc @@ -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 --git a/tools/gyp/test/win/compiler-flags/rtti-on.cc b/tools/gyp/test/win/compiler-flags/rtti-on.cc new file mode 100644 index 00000000000000..2d3ad03ae4d6a0 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/rtti-on.cc @@ -0,0 +1,11 @@ +// 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. + +#ifndef _CPPRTTI +#error +#endif + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/rtti.gyp b/tools/gyp/test/win/compiler-flags/rtti.gyp new file mode 100644 index 00000000000000..704cd58f5a5542 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/rtti.gyp @@ -0,0 +1,37 @@ +# 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_rtti_off', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeTypeInfo': 'false', + 'WarnAsError': 'true' + } + }, + 'sources': ['rtti-on.cc'], + }, + { + 'target_name': 'test_rtti_on', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeTypeInfo': 'true', + 'WarnAsError': 'true' + } + }, + 'sources': ['rtti-on.cc'], + }, + { + 'target_name': 'test_rtti_unset', + 'type': 'executable', + 'msvs_settings': { + }, + 'sources': ['rtti-on.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/compiler-flags/runtime-checks.cc b/tools/gyp/test/win/compiler-flags/runtime-checks.cc new file mode 100644 index 00000000000000..fdb811da8767fb --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/runtime-checks.cc @@ -0,0 +1,11 @@ +// 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. + +#ifndef __MSVC_RUNTIME_CHECKS +#error +#endif + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/runtime-checks.gyp b/tools/gyp/test/win/compiler-flags/runtime-checks.gyp new file mode 100644 index 00000000000000..8ea30920577b6c --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/runtime-checks.gyp @@ -0,0 +1,29 @@ +# 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_brc_none', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'Optimization': '0', + } + }, + 'sources': ['runtime-checks.cc'], + }, + { + 'target_name': 'test_brc_1', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'Optimization': '0', + 'BasicRuntimeChecks': '3' + } + }, + 'sources': ['runtime-checks.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/compiler-flags/runtime-library-md.cc b/tools/gyp/test/win/compiler-flags/runtime-library-md.cc new file mode 100644 index 00000000000000..87c83021d4e795 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/runtime-library-md.cc @@ -0,0 +1,19 @@ +// 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. + +#ifndef _MT +#error +#endif + +#ifdef _DEBUG +#error +#endif + +#ifndef _DLL +#error +#endif + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/runtime-library-mdd.cc b/tools/gyp/test/win/compiler-flags/runtime-library-mdd.cc new file mode 100644 index 00000000000000..9f175e493e03ec --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/runtime-library-mdd.cc @@ -0,0 +1,19 @@ +// 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. + +#ifndef _MT +#error +#endif + +#ifndef _DEBUG +#error +#endif + +#ifndef _DLL +#error +#endif + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/runtime-library-mt.cc b/tools/gyp/test/win/compiler-flags/runtime-library-mt.cc new file mode 100644 index 00000000000000..27e62b63dbe3d9 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/runtime-library-mt.cc @@ -0,0 +1,19 @@ +// 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. + +#ifndef _MT +#error +#endif + +#ifdef _DEBUG +#error +#endif + +#ifdef _DLL +#error +#endif + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/runtime-library-mtd.cc b/tools/gyp/test/win/compiler-flags/runtime-library-mtd.cc new file mode 100644 index 00000000000000..a9921db9e2f418 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/runtime-library-mtd.cc @@ -0,0 +1,19 @@ +// 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. + +#ifndef _MT +#error +#endif + +#ifndef _DEBUG +#error +#endif + +#ifdef _DLL +#error +#endif + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/runtime-library.gyp b/tools/gyp/test/win/compiler-flags/runtime-library.gyp new file mode 100644 index 00000000000000..04afc391c77c43 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/runtime-library.gyp @@ -0,0 +1,48 @@ +# 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_rl_md', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeLibrary': '2' + } + }, + 'sources': ['runtime-library-md.cc'], + }, + { + 'target_name': 'test_rl_mdd', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeLibrary': '3' + } + }, + 'sources': ['runtime-library-mdd.cc'], + }, + { + 'target_name': 'test_rl_mt', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeLibrary': '0' + } + }, + 'sources': ['runtime-library-mt.cc'], + }, + { + 'target_name': 'test_rl_mtd', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeLibrary': '1' + } + }, + 'sources': ['runtime-library-mtd.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/compiler-flags/subdir/header.h b/tools/gyp/test/win/compiler-flags/subdir/header.h new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/win/compiler-flags/treat-wchar-t-as-built-in-type.gyp b/tools/gyp/test/win/compiler-flags/treat-wchar-t-as-built-in-type.gyp new file mode 100644 index 00000000000000..456fe047d04fb1 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/treat-wchar-t-as-built-in-type.gyp @@ -0,0 +1,33 @@ +# Copyright (c) 2010 Google 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_treat_wchar_t_as_built_in_type_negative', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'TreatWChar_tAsBuiltInType': 'false', + }, + }, + 'sources': [ + 'treat-wchar-t-as-built-in-type1.cc', + ], + }, + { + 'target_name': 'test_treat_wchar_t_as_built_in_type_positive', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'TreatWChar_tAsBuiltInType': 'true', + }, + }, + 'sources': [ + 'treat-wchar-t-as-built-in-type2.cc', + ], + }, + + ], +} diff --git a/tools/gyp/test/win/compiler-flags/treat-wchar-t-as-built-in-type1.cc b/tools/gyp/test/win/compiler-flags/treat-wchar-t-as-built-in-type1.cc new file mode 100644 index 00000000000000..fc1ed0b7ea8f84 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/treat-wchar-t-as-built-in-type1.cc @@ -0,0 +1,11 @@ +// 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. + +#ifdef _NATIVE_WCHAR_T_DEFINED +#error +#endif + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/treat-wchar-t-as-built-in-type2.cc b/tools/gyp/test/win/compiler-flags/treat-wchar-t-as-built-in-type2.cc new file mode 100644 index 00000000000000..28ab94f742b469 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/treat-wchar-t-as-built-in-type2.cc @@ -0,0 +1,11 @@ +// 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. + +#ifndef _NATIVE_WCHAR_T_DEFINED +#error +#endif + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/uninit.cc b/tools/gyp/test/win/compiler-flags/uninit.cc new file mode 100644 index 00000000000000..a9d5f5d4833131 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/uninit.cc @@ -0,0 +1,13 @@ +// 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. + +// Should trigger C6001: using uninitialized memory for |i|. +int f(bool b) { + int i; + if (b) + i = 0; + return i; +} + +int main() {} diff --git a/tools/gyp/test/win/compiler-flags/warning-as-error.cc b/tools/gyp/test/win/compiler-flags/warning-as-error.cc new file mode 100644 index 00000000000000..fd2130aca59e6b --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/warning-as-error.cc @@ -0,0 +1,9 @@ +// 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. + +int main() { + // Cause a warning, even at /W1 + int export; + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/warning-as-error.gyp b/tools/gyp/test/win/compiler-flags/warning-as-error.gyp new file mode 100644 index 00000000000000..d71f26114104f4 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/warning-as-error.gyp @@ -0,0 +1,37 @@ +# 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_warn_as_error_false', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarnAsError': 'false' + } + }, + 'sources': ['warning-as-error.cc'] + }, + { + 'target_name': 'test_warn_as_error_true', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarnAsError': 'true' + } + }, + 'sources': ['warning-as-error.cc'] + }, + { + 'target_name': 'test_warn_as_error_unset', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + } + }, + 'sources': ['warning-as-error.cc'] + }, + ] +} diff --git a/tools/gyp/test/win/compiler-flags/warning-level.gyp b/tools/gyp/test/win/compiler-flags/warning-level.gyp new file mode 100644 index 00000000000000..2297aa7cacf970 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/warning-level.gyp @@ -0,0 +1,115 @@ +# 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': [ + # Level 1 + { + 'target_name': 'test_wl1_fail', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarningLevel': '1', + 'WarnAsError': 'true', + } + }, + 'sources': ['warning-level1.cc'], + }, + { + 'target_name': 'test_wl1_pass', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarningLevel': '1', + 'WarnAsError': 'true', + } + }, + 'sources': ['warning-level2.cc'], + }, + + # Level 2 + { + 'target_name': 'test_wl2_fail', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarningLevel': '2', + 'WarnAsError': 'true', + } + }, + 'sources': ['warning-level2.cc'], + }, + { + 'target_name': 'test_wl2_pass', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarningLevel': '2', + 'WarnAsError': 'true', + } + }, + 'sources': ['warning-level3.cc'], + }, + + # Level 3 + { + 'target_name': 'test_wl3_fail', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarningLevel': '3', + 'WarnAsError': 'true', + } + }, + 'sources': ['warning-level3.cc'], + }, + { + 'target_name': 'test_wl3_pass', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarningLevel': '3', + 'WarnAsError': 'true', + } + }, + 'sources': ['warning-level4.cc'], + }, + + + # Level 4 + { + 'target_name': 'test_wl4_fail', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarningLevel': '4', + 'WarnAsError': 'true', + } + }, + 'sources': ['warning-level4.cc'], + }, + + # Default level + { + 'target_name': 'test_def_fail', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarnAsError': 'true', + } + }, + 'sources': ['warning-level1.cc'], + }, + { + 'target_name': 'test_def_pass', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + } + }, + 'sources': ['warning-level2.cc'], + }, + + ] +} diff --git a/tools/gyp/test/win/compiler-flags/warning-level1.cc b/tools/gyp/test/win/compiler-flags/warning-level1.cc new file mode 100644 index 00000000000000..119578d694004a --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/warning-level1.cc @@ -0,0 +1,8 @@ +// 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. + +int main() { + int export; // Cause a level 1 warning (C4237). + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/warning-level2.cc b/tools/gyp/test/win/compiler-flags/warning-level2.cc new file mode 100644 index 00000000000000..9a2670318069fb --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/warning-level2.cc @@ -0,0 +1,14 @@ +// 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. + +int f(int x) { + return 0; +} + +int main() { + double x = 10.1; + // Cause a level 2 warning (C4243). + return f(x); + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/warning-level3.cc b/tools/gyp/test/win/compiler-flags/warning-level3.cc new file mode 100644 index 00000000000000..e0a9f3cdd98261 --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/warning-level3.cc @@ -0,0 +1,11 @@ +// 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. + +// Cause a level 3 warning (C4359). +struct __declspec(align(8)) C8 { __int64 i; }; +struct __declspec(align(4)) C4 { C8 m8; }; + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/compiler-flags/warning-level4.cc b/tools/gyp/test/win/compiler-flags/warning-level4.cc new file mode 100644 index 00000000000000..48a4fb70181bdd --- /dev/null +++ b/tools/gyp/test/win/compiler-flags/warning-level4.cc @@ -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. + +int main() { + const int i = -1; + // Cause a level 4 warning (C4245). + unsigned int j = i; + return 0; +} diff --git a/tools/gyp/test/win/enable-winrt/dllmain.cc b/tools/gyp/test/win/enable-winrt/dllmain.cc new file mode 100644 index 00000000000000..dedd83c3f66d60 --- /dev/null +++ b/tools/gyp/test/win/enable-winrt/dllmain.cc @@ -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 --git a/tools/gyp/test/win/enable-winrt/enable-winrt.gyp b/tools/gyp/test/win/enable-winrt/enable-winrt.gyp new file mode 100644 index 00000000000000..69f70189db94de --- /dev/null +++ b/tools/gyp/test/win/enable-winrt/enable-winrt.gyp @@ -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 --git a/tools/gyp/test/win/generator-output-different-drive/gyptest-generator-output-different-drive.py b/tools/gyp/test/win/generator-output-different-drive/gyptest-generator-output-different-drive.py new file mode 100644 index 00000000000000..96a30ec5b98861 --- /dev/null +++ b/tools/gyp/test/win/generator-output-different-drive/gyptest-generator-output-different-drive.py @@ -0,0 +1,44 @@ +#!/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. + +""" +Test that the generator output can be written to a different drive on Windows. +""" + +import os +import TestGyp +import string +import subprocess +import sys + + +if sys.platform == 'win32': + import win32api + + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + def GetFirstFreeDriveLetter(): + """ Returns the first unused Windows drive letter in [A, Z] """ + all_letters = [c for c in string.ascii_uppercase] + in_use = win32api.GetLogicalDriveStrings() + free = list(set(all_letters) - set(in_use)) + return free[0] + + output_dir = os.path.join('different-drive', 'output') + if not os.path.isdir(os.path.abspath(output_dir)): + os.makedirs(os.path.abspath(output_dir)) + output_drive = GetFirstFreeDriveLetter() + subprocess.call(['subst', '%c:' % output_drive, os.path.abspath(output_dir)]) + try: + test.run_gyp('prog.gyp', '--generator-output=%s' % ( + os.path.join(output_drive, 'output'))) + test.build('prog.gyp', test.ALL, chdir=os.path.join(output_drive, 'output')) + test.built_file_must_exist('program', chdir=os.path.join(output_drive, + 'output'), + type=test.EXECUTABLE) + test.pass_test() + finally: + subprocess.call(['subst', '%c:' % output_drive, '/D']) diff --git a/tools/gyp/test/win/generator-output-different-drive/prog.c b/tools/gyp/test/win/generator-output-different-drive/prog.c new file mode 100644 index 00000000000000..7937f5d07a0c25 --- /dev/null +++ b/tools/gyp/test/win/generator-output-different-drive/prog.c @@ -0,0 +1,10 @@ +// 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. + +#include + +int main(void) { + printf("Hello from prog.c\n"); + return 0; +} diff --git a/tools/gyp/gyp b/tools/gyp/test/win/generator-output-different-drive/prog.gyp old mode 100755 new mode 100644 similarity index 53% rename from tools/gyp/gyp rename to tools/gyp/test/win/generator-output-different-drive/prog.gyp index 1b8b9bdfb05f58..92f53e5da56f44 --- a/tools/gyp/gyp +++ b/tools/gyp/test/win/generator-output-different-drive/prog.gyp @@ -1,8 +1,15 @@ -#!/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. -set -e -base=$(dirname "$0") -exec python "${base}/gyp_main.py" "$@" +{ + 'targets': [ + { + 'target_name': 'program', + 'type': 'executable', + 'sources': [ + 'prog.c', + ], + }, + ], +} diff --git a/tools/gyp/test/win/gyptest-asm-files.py b/tools/gyp/test/win/gyptest-asm-files.py new file mode 100644 index 00000000000000..007b52eb267688 --- /dev/null +++ b/tools/gyp/test/win/gyptest-asm-files.py @@ -0,0 +1,26 @@ +#!/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. + +""" +Make sure .s files aren't passed to cl. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'asm-files' + test.run_gyp('asm-files.gyp', chdir=CHDIR) + # The compiler will error out if it's passed the .s files, so just make sure + # the build succeeds. The compiler doesn't directly support building + # assembler files on Windows, they have to be built explicitly with a + # third-party tool. + test.build('asm-files.gyp', test.ALL, chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-additional-include-dirs.py b/tools/gyp/test/win/gyptest-cl-additional-include-dirs.py new file mode 100644 index 00000000000000..1fabfa97526e09 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-additional-include-dirs.py @@ -0,0 +1,22 @@ +#!/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. + +""" +Make sure additional include dirs are extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('additional-include-dirs.gyp', chdir=CHDIR) + test.build('additional-include-dirs.gyp', test.ALL, chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-additional-options.py b/tools/gyp/test/win/gyptest-cl-additional-options.py new file mode 100644 index 00000000000000..e9aea10dc98fa3 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-additional-options.py @@ -0,0 +1,28 @@ +#!/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. + +""" +Make sure additional manual compiler flags are extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('additional-options.gyp', chdir=CHDIR) + + # Warning level not overidden, must fail. + test.build('additional-options.gyp', 'test_additional_none', chdir=CHDIR, + status=1) + + # Warning level is overridden, must succeed. + test.build('additional-options.gyp', 'test_additional_one', chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-analysis.py b/tools/gyp/test/win/gyptest-cl-analysis.py new file mode 100644 index 00000000000000..7b3b9897f5a7e0 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-analysis.py @@ -0,0 +1,30 @@ +#!/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. + +""" +Make sure PREfast (code analysis) setting is extracted properly. +""" + +import TestGyp + +import os +import sys + +if (sys.platform == 'win32' and + int(os.environ.get('GYP_MSVS_VERSION', 0)) >= 2012): + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('analysis.gyp', chdir=CHDIR) + + # Analysis enabled, should fail. + test.build('analysis.gyp', 'test_analysis_on', chdir=CHDIR, status=1) + + # Analysis not enabled, or unspecified, should pass. + test.build('analysis.gyp', 'test_analysis_off', chdir=CHDIR) + test.build('analysis.gyp', 'test_analysis_unspec', chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-buffer-security-check.py b/tools/gyp/test/win/gyptest-cl-buffer-security-check.py new file mode 100644 index 00000000000000..e22869c3d35e3d --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-buffer-security-check.py @@ -0,0 +1,53 @@ +#!/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. + +""" +Make sure buffer security check setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('buffer-security-check.gyp', chdir=CHDIR) + test.build('buffer-security-check.gyp', chdir=CHDIR) + + def GetDisassemblyOfMain(exe): + # The standard library uses buffer security checks independent of our + # buffer security settings, so we extract just our code (i.e. main()) to + # check against. + full_path = test.built_file_path(exe, chdir=CHDIR) + output = test.run_dumpbin('/disasm', full_path) + result = [] + in_main = False + for line in output.splitlines(): + if line == '_main:': + in_main = True + elif in_main: + # Disassembly of next function starts. + if line.startswith('_'): + break + result.append(line) + return '\n'.join(result) + + # Buffer security checks are on by default, make sure security_cookie + # appears in the disassembly of our code. + if 'security_cookie' not in GetDisassemblyOfMain('test_bsc_unset.exe'): + test.fail_test() + + # Explicitly on. + if 'security_cookie' not in GetDisassemblyOfMain('test_bsc_on.exe'): + test.fail_test() + + # Explicitly off, shouldn't be a reference to the security cookie. + if 'security_cookie' in GetDisassemblyOfMain('test_bsc_off.exe'): + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-calling-convention.py b/tools/gyp/test/win/gyptest-cl-calling-convention.py new file mode 100644 index 00000000000000..b5fdc477440939 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-calling-convention.py @@ -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 --git a/tools/gyp/test/win/gyptest-cl-character-set.py b/tools/gyp/test/win/gyptest-cl-character-set.py new file mode 100644 index 00000000000000..7fabb6722a87f1 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-character-set.py @@ -0,0 +1,22 @@ +#!/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. + +""" +Make sure character set setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('character-set.gyp', chdir=CHDIR) + test.build('character-set.gyp', test.ALL, chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-compile-as-managed.py b/tools/gyp/test/win/gyptest-cl-compile-as-managed.py new file mode 100644 index 00000000000000..0d7b420485e866 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-compile-as-managed.py @@ -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 --git a/tools/gyp/test/win/gyptest-cl-compile-as-winrt.py b/tools/gyp/test/win/gyptest-cl-compile-as-winrt.py new file mode 100644 index 00000000000000..3e0168b67876a8 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-compile-as-winrt.py @@ -0,0 +1,20 @@ +# Copyright (c) 2016 Google 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 TestGyp + +import os +import sys + +if (sys.platform == 'win32' and + int(os.environ.get('GYP_MSVS_VERSION', 0)) >= 2015): + test = TestGyp.TestGyp(formats=['msvs']) + + CHDIR = 'compiler-flags' + + test.run_gyp('compile-as-winrt.gyp', chdir=CHDIR) + + test.build('compile-as-winrt.gyp', 'test-compile-as-winrt', chdir=CHDIR) + + test.pass_test() \ No newline at end of file diff --git a/tools/gyp/test/win/gyptest-cl-debug-format.py b/tools/gyp/test/win/gyptest-cl-debug-format.py new file mode 100644 index 00000000000000..431a53ab888c17 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-debug-format.py @@ -0,0 +1,39 @@ +#!/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. + +""" +Make sure debug format settings are extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('debug-format.gyp', chdir=CHDIR) + + # While there's ways to via .pdb contents, the .pdb doesn't include + # which style the debug information was created from, so we resort to just + # verifying the flags are correct on the command line. + + ninja_file = test.built_file_path('obj/test-debug-format-off.ninja', chdir=CHDIR) + test.must_not_contain(ninja_file, '/Z7') + test.must_not_contain(ninja_file, '/Zi') + test.must_not_contain(ninja_file, '/ZI') + + ninja_file = test.built_file_path('obj/test-debug-format-oldstyle.ninja', chdir=CHDIR) + test.must_contain(ninja_file, '/Z7') + + ninja_file = test.built_file_path('obj/test-debug-format-pdb.ninja', chdir=CHDIR) + test.must_contain(ninja_file, '/Zi') + + ninja_file = test.built_file_path('obj/test-debug-format-editcontinue.ninja', chdir=CHDIR) + test.must_contain(ninja_file, '/ZI') + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-default-char-is-unsigned.py b/tools/gyp/test/win/gyptest-cl-default-char-is-unsigned.py new file mode 100644 index 00000000000000..d20f6742f5e17e --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-default-char-is-unsigned.py @@ -0,0 +1,22 @@ +#!/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. + +""" +Make sure DefaultCharIsUnsigned option is functional. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('default-char-is-unsigned.gyp', chdir=CHDIR) + test.build('default-char-is-unsigned.gyp', test.ALL, chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-disable-specific-warnings.py b/tools/gyp/test/win/gyptest-cl-disable-specific-warnings.py new file mode 100644 index 00000000000000..cb253aff621518 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-disable-specific-warnings.py @@ -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 --git a/tools/gyp/test/win/gyptest-cl-enable-enhanced-instruction-set.py b/tools/gyp/test/win/gyptest-cl-enable-enhanced-instruction-set.py new file mode 100644 index 00000000000000..f34e67112527a3 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-enable-enhanced-instruction-set.py @@ -0,0 +1,49 @@ +#!/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. +""" + +from __future__ import print_function + +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 --git a/tools/gyp/test/win/gyptest-cl-exception-handling.py b/tools/gyp/test/win/gyptest-cl-exception-handling.py new file mode 100644 index 00000000000000..5738a5407144b4 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-exception-handling.py @@ -0,0 +1,33 @@ +#!/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. + +""" +Make sure exception handling settings are extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('exception-handling.gyp', chdir=CHDIR) + + # Must fail. + test.build('exception-handling.gyp', 'test_eh_off', chdir=CHDIR, + status=1) + + # Must succeed. + test.build('exception-handling.gyp', 'test_eh_s', chdir=CHDIR) + test.build('exception-handling.gyp', 'test_eh_a', chdir=CHDIR) + + # Error code must be 1 if EHa, and 2 if EHsc. + test.run_built_executable('test_eh_a', chdir=CHDIR, status=1) + test.run_built_executable('test_eh_s', chdir=CHDIR, status=2) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-floating-point-model.py b/tools/gyp/test/win/gyptest-cl-floating-point-model.py new file mode 100644 index 00000000000000..86ff4785a07a7d --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-floating-point-model.py @@ -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 --git a/tools/gyp/test/win/gyptest-cl-force-include-files.py b/tools/gyp/test/win/gyptest-cl-force-include-files.py new file mode 100644 index 00000000000000..b73b8bd50320ef --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-force-include-files.py @@ -0,0 +1,22 @@ +#!/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. + +""" +Make sure ForcedIncludeFiles option is functional. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('force-include-files.gyp', chdir=CHDIR) + test.build('force-include-files.gyp', test.ALL, chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-function-level-linking.py b/tools/gyp/test/win/gyptest-cl-function-level-linking.py new file mode 100644 index 00000000000000..a0106588e4ef36 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-function-level-linking.py @@ -0,0 +1,52 @@ +#!/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. + +""" +Make sure function-level linking setting is extracted properly. +""" + +from __future__ import print_function + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('function-level-linking.gyp', chdir=CHDIR) + test.build('function-level-linking.gyp', test.ALL, chdir=CHDIR) + + def CheckForSectionString(binary, search_for, should_exist): + output = test.run_dumpbin('/headers', binary) + if should_exist and search_for not in output: + print('Did not find "%s" in %s' % (search_for, binary)) + test.fail_test() + elif not should_exist and search_for in output: + print('Found "%s" in %s (and shouldn\'t have)' % (search_for, binary)) + test.fail_test() + + def Object(proj, obj): + sep = '.' if test.format == 'ninja' else '\\' + return 'obj\\%s%s%s' % (proj, sep, obj) + + look_for = '''COMDAT; sym= "int __cdecl comdat_function''' + + # When function level linking is on, the functions should be listed as + # separate comdat entries. + + CheckForSectionString( + test.built_file_path(Object('test_fll_on', 'function-level-linking.obj'), chdir=CHDIR), + look_for, + should_exist=True) + + CheckForSectionString( + test.built_file_path(Object('test_fll_off', 'function-level-linking.obj'), chdir=CHDIR), + look_for, + should_exist=False) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-optimizations.py b/tools/gyp/test/win/gyptest-cl-optimizations.py new file mode 100644 index 00000000000000..c4d988ee9dd6b4 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-optimizations.py @@ -0,0 +1,92 @@ +#!/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. + +""" +Make sure optimization settings are extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('optimizations.gyp', chdir=CHDIR) + + # It's hard to map flags to output contents in a non-fragile way (especially + # handling both 2008/2010), so just verify the correct ninja command line + # contents. + + ninja_file = test.built_file_path('obj/test_opt_off.ninja', chdir=CHDIR) + test.must_contain(ninja_file, 'cflags = /Od') + + ninja_file = test.built_file_path('obj/test_opt_lev_size.ninja', chdir=CHDIR) + test.must_contain(ninja_file, 'cflags = /O1') + + ninja_file = test.built_file_path('obj/test_opt_lev_speed.ninja', chdir=CHDIR) + test.must_contain(ninja_file, 'cflags = /O2') + + ninja_file = test.built_file_path('obj/test_opt_lev_max.ninja', chdir=CHDIR) + test.must_contain(ninja_file, 'cflags = /Ox') + + ninja_file = test.built_file_path('obj/test_opt_unset.ninja', chdir=CHDIR) + test.must_not_contain(ninja_file, '/Od') + test.must_not_contain(ninja_file, '/O1') + test.must_not_contain(ninja_file, '/Ox') + # Set by default if none specified. + test.must_contain(ninja_file, '/O2') + + ninja_file = test.built_file_path('obj/test_opt_fpo.ninja', chdir=CHDIR) + test.must_contain(ninja_file, '/Oy') + test.must_not_contain(ninja_file, '/Oy-') + + ninja_file = test.built_file_path('obj/test_opt_fpo_off.ninja', chdir=CHDIR) + test.must_contain(ninja_file, '/Oy-') + + ninja_file = test.built_file_path('obj/test_opt_intrinsic.ninja', chdir=CHDIR) + test.must_contain(ninja_file, '/Oi') + test.must_not_contain(ninja_file, '/Oi-') + + ninja_file = test.built_file_path('obj/test_opt_intrinsic_off.ninja', chdir=CHDIR) + test.must_contain(ninja_file, '/Oi-') + + ninja_file = test.built_file_path('obj/test_opt_inline_off.ninja', chdir=CHDIR) + test.must_contain(ninja_file, '/Ob0') + + ninja_file = test.built_file_path('obj/test_opt_inline_manual.ninja', chdir=CHDIR) + test.must_contain(ninja_file, '/Ob1') + + ninja_file = test.built_file_path('obj/test_opt_inline_auto.ninja', chdir=CHDIR) + test.must_contain(ninja_file, '/Ob2') + + ninja_file = test.built_file_path('obj/test_opt_neither.ninja', chdir=CHDIR) + test.must_not_contain(ninja_file, '/Os') + test.must_not_contain(ninja_file, '/Ot') + + ninja_file = test.built_file_path('obj/test_opt_size.ninja', chdir=CHDIR) + test.must_contain(ninja_file, '/Os') + + ninja_file = test.built_file_path('obj/test_opt_speed.ninja', chdir=CHDIR) + test.must_contain(ninja_file, '/Ot') + + ninja_file = test.built_file_path('obj/test_opt_wpo.ninja', chdir=CHDIR) + test.must_contain(ninja_file, '/GL') + + ninja_file = test.built_file_path('obj/test_opt_sp.ninja', chdir=CHDIR) + test.must_contain(ninja_file, '/GF') + + ninja_file = test.built_file_path('obj/test_opt_sp_off.ninja', chdir=CHDIR) + test.must_not_contain(ninja_file, '/GF') + + ninja_file = test.built_file_path('obj/test_opt_fso.ninja', chdir=CHDIR) + test.must_contain(ninja_file, '/GT') + + ninja_file = test.built_file_path('obj/test_opt_fso_off.ninja', chdir=CHDIR) + test.must_not_contain(ninja_file, '/GT') + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-pdbname-override.py b/tools/gyp/test/win/gyptest-cl-pdbname-override.py new file mode 100644 index 00000000000000..da9b49af160dd2 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-pdbname-override.py @@ -0,0 +1,27 @@ +#!/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. + +""" +Make sure pdb is named as expected (shared between .cc files). +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp() + + CHDIR = 'compiler-flags' + test.run_gyp('pdbname-override.gyp', chdir=CHDIR) + test.build('pdbname-override.gyp', test.ALL, chdir=CHDIR) + + # Confirm that the pdb generated by the compiler was renamed (and we also + # have the linker generated one). + test.built_file_must_exist('compiler_generated.pdb', chdir=CHDIR) + test.built_file_must_exist('linker_generated.pdb', chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-pdbname.py b/tools/gyp/test/win/gyptest-cl-pdbname.py new file mode 100644 index 00000000000000..f09ac233cd3fec --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-pdbname.py @@ -0,0 +1,30 @@ +#!/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 pdb is named as expected (shared between .cc files). +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('pdbname.gyp', chdir=CHDIR) + test.build('pdbname.gyp', test.ALL, chdir=CHDIR) + + # 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.cc.pdb', chdir=CHDIR) + + # Confirm that there should be a .pdb alongside the executable. + test.built_file_must_exist('test_pdbname.exe', chdir=CHDIR) + test.built_file_must_exist('test_pdbname.exe.pdb', chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-rtti.py b/tools/gyp/test/win/gyptest-cl-rtti.py new file mode 100644 index 00000000000000..d49a09437959b0 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-rtti.py @@ -0,0 +1,30 @@ +#!/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. + +""" +Make sure RTTI setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('rtti.gyp', chdir=CHDIR) + + # Must fail. + test.build('rtti.gyp', 'test_rtti_off', chdir=CHDIR, status=1) + + # Must succeed. + test.build('rtti.gyp', 'test_rtti_on', chdir=CHDIR) + + # Must succeed. + test.build('rtti.gyp', 'test_rtti_unset', chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-runtime-checks.py b/tools/gyp/test/win/gyptest-cl-runtime-checks.py new file mode 100644 index 00000000000000..4fd529f8927978 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-runtime-checks.py @@ -0,0 +1,30 @@ +#!/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. + +""" +Make sure RTC setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('runtime-checks.gyp', chdir=CHDIR) + + # Runtime checks disabled, should fail. + test.build('runtime-checks.gyp', 'test_brc_none', chdir=CHDIR, status=1) + + # Runtime checks enabled, should pass. + test.build('runtime-checks.gyp', 'test_brc_1', chdir=CHDIR) + + # TODO(scottmg): There are other less frequently used/partial options, but + # it's not clear how to verify them, so ignore for now. + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-runtime-library.py b/tools/gyp/test/win/gyptest-cl-runtime-library.py new file mode 100644 index 00000000000000..53c149297bd3e1 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-runtime-library.py @@ -0,0 +1,22 @@ +#!/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. + +""" +Make sure runtime C library setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('runtime-library.gyp', chdir=CHDIR) + test.build('runtime-library.gyp', test.ALL, chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-treat-wchar-t-as-built-in-type.py b/tools/gyp/test/win/gyptest-cl-treat-wchar-t-as-built-in-type.py new file mode 100644 index 00000000000000..ca35fb55a0ebd6 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-treat-wchar-t-as-built-in-type.py @@ -0,0 +1,22 @@ +#!/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. + +""" +Make sure TreatWChar_tAsBuiltInType option is functional. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('treat-wchar-t-as-built-in-type.gyp', chdir=CHDIR) + test.build('treat-wchar-t-as-built-in-type.gyp', test.ALL, chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-warning-as-error.py b/tools/gyp/test/win/gyptest-cl-warning-as-error.py new file mode 100644 index 00000000000000..d4ef1b362b5043 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-warning-as-error.py @@ -0,0 +1,30 @@ +#!/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. + +""" +Make sure warning-as-error is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('warning-as-error.gyp', chdir=CHDIR) + + # The source file contains a warning, so if WarnAsError is false (or + # default, which is also false), then the build should succeed, otherwise it + # must fail. + + test.build('warning-as-error.gyp', 'test_warn_as_error_false', chdir=CHDIR) + test.build('warning-as-error.gyp', 'test_warn_as_error_unset', chdir=CHDIR) + test.build('warning-as-error.gyp', 'test_warn_as_error_true', chdir=CHDIR, + status=1) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-cl-warning-level.py b/tools/gyp/test/win/gyptest-cl-warning-level.py new file mode 100644 index 00000000000000..62a5b39b6a28f9 --- /dev/null +++ b/tools/gyp/test/win/gyptest-cl-warning-level.py @@ -0,0 +1,41 @@ +#!/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. + +""" +Make sure warning level is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('warning-level.gyp', chdir=CHDIR) + + # A separate target for each warning level: one pass (compiling a file + # containing a warning that's above the specified level); and one fail + # (compiling a file at the specified level). No pass for 4 of course, + # because it would have to have no warnings. The default warning level is + # equivalent to level 1. + + test.build('warning-level.gyp', 'test_wl1_fail', chdir=CHDIR, status=1) + test.build('warning-level.gyp', 'test_wl1_pass', chdir=CHDIR) + + test.build('warning-level.gyp', 'test_wl2_fail', chdir=CHDIR, status=1) + test.build('warning-level.gyp', 'test_wl2_pass', chdir=CHDIR) + + test.build('warning-level.gyp', 'test_wl3_fail', chdir=CHDIR, status=1) + test.build('warning-level.gyp', 'test_wl3_pass', chdir=CHDIR) + + test.build('warning-level.gyp', 'test_wl4_fail', chdir=CHDIR, status=1) + + test.build('warning-level.gyp', 'test_def_fail', chdir=CHDIR, status=1) + test.build('warning-level.gyp', 'test_def_pass', chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-command-quote.py b/tools/gyp/test/win/gyptest-command-quote.py new file mode 100644 index 00000000000000..656a69da5302d8 --- /dev/null +++ b/tools/gyp/test/win/gyptest-command-quote.py @@ -0,0 +1,42 @@ +#!/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. + +""" + +Make sure the program in a command can be a called batch file, or an +application in the path. Specifically, this means not quoting something like +"call x.bat", lest the shell look for a program named "call x.bat", rather +than calling "x.bat". +""" + +from __future__ import print_function + +import TestGyp + +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) + + test.build('command-quote.gyp', 'test_batch', chdir=CHDIR) + test.build('command-quote.gyp', 'test_call_separate', chdir=CHDIR) + test.build('command-quote.gyp', 'test_with_double_quotes', chdir=CHDIR) + test.build('command-quote.gyp', 'test_with_single_quotes', chdir=CHDIR) + + # We confirm that this fails because other generators don't handle spaces in + # inputs so it's preferable to not have it work here. + test.build('command-quote.gyp', 'test_with_spaces', chdir=CHDIR, status=1) + + CHDIR = 'command-quote/subdir/and/another' + test.run_gyp('in-subdir.gyp', chdir=CHDIR) + test.build('in-subdir.gyp', 'test_batch_depth', chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-crosscompile-ar.py b/tools/gyp/test/win/gyptest-crosscompile-ar.py new file mode 100644 index 00000000000000..dc75d96a843f84 --- /dev/null +++ b/tools/gyp/test/win/gyptest-crosscompile-ar.py @@ -0,0 +1,29 @@ +#!/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. + +""" +Verifies that ar_host is set correctly when enabling cross-compile on windows. +""" + +import TestGyp + +import sys +import os + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['ninja']) + + CHDIR = 'lib-crosscompile' + oldenv = os.environ.copy() + try: + os.environ['GYP_CROSSCOMPILE'] = '1' + test.run_gyp('use_host_ar.gyp', chdir=CHDIR) + finally: + os.environ.clear() + os.environ.update(oldenv) + + test.build('use_host_ar.gyp', test.ALL, chdir=CHDIR) + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-lib-ltcg.py b/tools/gyp/test/win/gyptest-lib-ltcg.py new file mode 100644 index 00000000000000..d1d7bad8407f24 --- /dev/null +++ b/tools/gyp/test/win/gyptest-lib-ltcg.py @@ -0,0 +1,22 @@ +#!/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. + +""" +Make sure LTCG setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'lib-flags' + test.run_gyp('ltcg.gyp', chdir=CHDIR) + test.build('ltcg.gyp', test.ALL, chdir=CHDIR) + test.must_not_contain_any_line(test.stdout(), ['restarting link with /LTCG']) + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-link-additional-deps.py b/tools/gyp/test/win/gyptest-link-additional-deps.py new file mode 100644 index 00000000000000..62c57366f9931a --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-additional-deps.py @@ -0,0 +1,22 @@ +#!/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. + +""" +Make sure additional library dependencies are handled. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('additional-deps.gyp', chdir=CHDIR) + test.build('additional-deps.gyp', test.ALL, chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-link-additional-options.py b/tools/gyp/test/win/gyptest-link-additional-options.py new file mode 100644 index 00000000000000..7e57ae47644def --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-additional-options.py @@ -0,0 +1,22 @@ +#!/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. + +""" +Make sure additional options are handled. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('additional-options.gyp', chdir=CHDIR) + test.build('additional-options.gyp', test.ALL, chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-link-aslr.py b/tools/gyp/test/win/gyptest-link-aslr.py new file mode 100644 index 00000000000000..e765017d3b9fc1 --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-aslr.py @@ -0,0 +1,35 @@ +#!/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. + +""" +Make sure aslr setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('aslr.gyp', chdir=CHDIR) + test.build('aslr.gyp', test.ALL, chdir=CHDIR) + + def HasDynamicBase(exe): + full_path = test.built_file_path(exe, chdir=CHDIR) + output = test.run_dumpbin('/headers', full_path) + return ' Dynamic base' in output + + # Default is to be on. + if not HasDynamicBase('test_aslr_default.exe'): + test.fail_test() + if HasDynamicBase('test_aslr_no.exe'): + test.fail_test() + if not HasDynamicBase('test_aslr_yes.exe'): + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-link-base-address.py b/tools/gyp/test/win/gyptest-link-base-address.py new file mode 100644 index 00000000000000..d58527ad7e9377 --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-base-address.py @@ -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 --git a/tools/gyp/test/win/gyptest-link-debug-info.py b/tools/gyp/test/win/gyptest-link-debug-info.py new file mode 100644 index 00000000000000..33e8ac48bf1acf --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-debug-info.py @@ -0,0 +1,26 @@ +#!/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. + +""" +Make sure debug info setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('debug-info.gyp', chdir=CHDIR) + test.build('debug-info.gyp', test.ALL, chdir=CHDIR) + + suffix = '.exe.pdb' if test.format == 'ninja' else '.pdb' + test.built_file_must_not_exist('test_debug_off%s' % suffix, chdir=CHDIR) + test.built_file_must_exist('test_debug_on%s' % suffix, chdir=CHDIR) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-link-default-libs.py b/tools/gyp/test/win/gyptest-link-default-libs.py new file mode 100644 index 00000000000000..5edf467913e679 --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-default-libs.py @@ -0,0 +1,22 @@ +#!/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. + +""" +Make sure we include the default libs. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('no-default-libs.gyp', chdir=CHDIR) + test.build('no-default-libs.gyp', test.ALL, chdir=CHDIR, status=1) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-link-deffile.py b/tools/gyp/test/win/gyptest-link-deffile.py new file mode 100644 index 00000000000000..94df874f857e1f --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-deffile.py @@ -0,0 +1,43 @@ +#!/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. + +""" +Make sure a .def file is handled in the link. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + + # Multiple .def files doesn't make any sense, should fail at generate time. + test.run_gyp('deffile-multiple.gyp', chdir=CHDIR, stderr=None, status=1) + + test.run_gyp('deffile.gyp', chdir=CHDIR) + test.build('deffile.gyp', test.ALL, chdir=CHDIR) + + def HasExport(binary, export): + full_path = test.built_file_path(binary, chdir=CHDIR) + output = test.run_dumpbin('/exports', full_path) + return export in output + + # Make sure we only have the export when the .def file is in use. + + if HasExport('test_deffile_dll_notexported.dll', 'AnExportedFunction'): + test.fail_test() + if not HasExport('test_deffile_dll_ok.dll', 'AnExportedFunction'): + test.fail_test() + + if HasExport('test_deffile_exe_notexported.exe', 'AnExportedFunction'): + test.fail_test() + if not HasExport('test_deffile_exe_ok.exe', 'AnExportedFunction'): + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-link-defrelink.py b/tools/gyp/test/win/gyptest-link-defrelink.py new file mode 100644 index 00000000000000..cb3f86bb0e5114 --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-defrelink.py @@ -0,0 +1,56 @@ +#!/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 a relink is performed when a .def file is touched. +""" + +from __future__ import print_function + +import TestGyp + +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' + target = 'test_deffile_dll_ok' + def_contents = test.read('linker-flags/deffile.def') + + # This first build makes sure everything is up to date. + test.run_gyp('deffile.gyp', chdir=CHDIR) + test.build('deffile.gyp', target, chdir=CHDIR) + test.up_to_date('deffile.gyp', target, chdir=CHDIR) + + def HasExport(binary, export): + full_path = test.built_file_path(binary, chdir=CHDIR) + output = test.run_dumpbin('/exports', full_path) + return export in output + + # Verify that only one function is exported. + if not HasExport('test_deffile_dll_ok.dll', 'AnExportedFunction'): + test.fail_test() + if HasExport('test_deffile_dll_ok.dll', 'AnotherExportedFunction'): + test.fail_test() + + # Add AnotherExportedFunction to the def file, then rebuild. If it doesn't + # relink the DLL, then the subsequent check for AnotherExportedFunction will + # fail. + new_def_contents = def_contents + "\n AnotherExportedFunction" + test.write('linker-flags/deffile.def', new_def_contents) + test.build('deffile.gyp', target, chdir=CHDIR) + test.up_to_date('deffile.gyp', target, chdir=CHDIR) + + if not HasExport('test_deffile_dll_ok.dll', 'AnExportedFunction'): + test.fail_test() + if not HasExport('test_deffile_dll_ok.dll', 'AnotherExportedFunction'): + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-link-delay-load-dlls.py b/tools/gyp/test/win/gyptest-link-delay-load-dlls.py new file mode 100644 index 00000000000000..3880247b4ae3a5 --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-delay-load-dlls.py @@ -0,0 +1,35 @@ +#!/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. + +""" +Make sure delay load setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('delay-load-dlls.gyp', chdir=CHDIR) + test.build('delay-load-dlls.gyp', test.ALL, chdir=CHDIR) + + prefix = 'contains the following delay load imports:' + shell32_look_for = prefix + '\r\n\r\n SHELL32.dll' + + output = test.run_dumpbin( + '/all', test.built_file_path('test_dld_none.exe', chdir=CHDIR)) + if prefix in output: + test.fail_test() + + output = test.run_dumpbin( + '/all', test.built_file_path('test_dld_shell32.exe', chdir=CHDIR)) + if shell32_look_for not in output: + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-link-embed-manifest.py b/tools/gyp/test/win/gyptest-link-embed-manifest.py new file mode 100644 index 00000000000000..741deb24f0c6db --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-embed-manifest.py @@ -0,0 +1,86 @@ +""" +Make sure manifests are embedded in binaries properly. Handling of +AdditionalManifestFiles is tested too. +""" + +import TestGyp + +import sys + +if not sys.platform == 'win32': + print('Only for Windows') + sys.exit(2) + +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).decode('utf-8', 'ignore') + 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('embed-manifest.gyp', chdir=CHDIR) +test.build('embed-manifest.gyp', test.ALL, chdir=CHDIR) + +# The following binaries must contain a manifest embedded. +test.fail_test(not extract_manifest(test.built_file_path('test_manifest_exe.exe', chdir=CHDIR), 1)) +test.fail_test(not extract_manifest(test.built_file_path('test_manifest_exe_inc.exe', chdir=CHDIR), 1)) +test.fail_test(not extract_manifest(test.built_file_path('test_manifest_dll.dll', chdir=CHDIR), 2)) +test.fail_test(not extract_manifest(test.built_file_path('test_manifest_dll_inc.dll', chdir=CHDIR), 2)) + +# Must contain the Win7 support GUID, but not the Vista one (from +# extra2.manifest). +test.fail_test( + '35138b9a-5d96-4fbd-8e2d-a2440225f93a' not in + extract_manifest(test.built_file_path('test_manifest_extra1.exe', chdir=CHDIR), 1)) +test.fail_test( + 'e2011457-1546-43c5-a5fe-008deee3d3f0' in + extract_manifest(test.built_file_path('test_manifest_extra1.exe', chdir=CHDIR), 1)) +# Must contain both. +test.fail_test( + '35138b9a-5d96-4fbd-8e2d-a2440225f93a' not in + extract_manifest(test.built_file_path('test_manifest_extra2.exe', chdir=CHDIR), 1)) +test.fail_test( + 'e2011457-1546-43c5-a5fe-008deee3d3f0' not in + extract_manifest(test.built_file_path('test_manifest_extra2.exe', chdir=CHDIR), 1)) + +# Same as extra2, but using list syntax instead. +test.fail_test( + '35138b9a-5d96-4fbd-8e2d-a2440225f93a' not in + extract_manifest(test.built_file_path('test_manifest_extra_list.exe', chdir=CHDIR), 1)) +test.fail_test( + 'e2011457-1546-43c5-a5fe-008deee3d3f0' not in + extract_manifest(test.built_file_path('test_manifest_extra_list.exe', chdir=CHDIR), 1)) + +# Test that incremental linking doesn't force manifest embedding. +test.fail_test(extract_manifest(test.built_file_path('test_manifest_exe_inc_no_embed.exe', chdir=CHDIR), 1)) + +test.pass_test() diff --git a/tools/gyp/test/win/gyptest-link-enable-uac.py b/tools/gyp/test/win/gyptest-link-enable-uac.py new file mode 100644 index 00000000000000..684b2238049432 --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-enable-uac.py @@ -0,0 +1,101 @@ +#!/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. + +""" +Verifies that embedding UAC information into the manifest works. +""" + +import TestGyp + +import sys +from xml.dom.minidom import parseString + +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('enable-uac.gyp', chdir=CHDIR) + test.build('enable-uac.gyp', test.ALL, chdir=CHDIR) + + # The following binaries must contain a manifest embedded. + test.fail_test(not extract_manifest(test.built_file_path('enable_uac.exe', chdir=CHDIR), 1)) + test.fail_test(not extract_manifest(test.built_file_path('enable_uac_no.exe', chdir=CHDIR), 1)) + test.fail_test(not extract_manifest(test.built_file_path('enable_uac_admin.exe', chdir=CHDIR), 1)) + + # Verify that + # is present. + manifest = parseString(extract_manifest( + test.built_file_path('enable_uac.exe', chdir=CHDIR), 1)) + execution_level = manifest.getElementsByTagName('requestedExecutionLevel') + test.fail_test(len(execution_level) != 1) + execution_level = execution_level[0].attributes + + def _has_key(node, key): + # 'in' doesn't work with the NamedNodeMap interface in Python2, + # but 'has_key' was removed from it in Python3, so we need to + # shim things :(. + if hasattr(node, 'has_key'): + return node.has_key(key) + return key in node + + test.fail_test(not ( + _has_key(execution_level, 'level') and + _has_key(execution_level, 'uiAccess') and + execution_level['level'].nodeValue == 'asInvoker' and + execution_level['uiAccess'].nodeValue == 'false')) + + # Verify that is not in the menifest. + manifest = parseString(extract_manifest( + test.built_file_path('enable_uac_no.exe', chdir=CHDIR), 1)) + execution_level = manifest.getElementsByTagName('requestedExecutionLevel') + test.fail_test(len(execution_level) != 0) + + # Verify that is present. + manifest = parseString(extract_manifest( + test.built_file_path('enable_uac_admin.exe', chdir=CHDIR), 1)) + execution_level = manifest.getElementsByTagName('requestedExecutionLevel') + test.fail_test(len(execution_level) != 1) + execution_level = execution_level[0].attributes + test.fail_test(not ( + _has_key(execution_level, 'level') and + _has_key(execution_level, 'uiAccess') and + execution_level['level'].nodeValue == 'requireAdministrator' and + execution_level['uiAccess'].nodeValue == 'true')) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-link-enable-winrt-app-revision.py b/tools/gyp/test/win/gyptest-link-enable-winrt-app-revision.py new file mode 100644 index 00000000000000..bf771163b9c0c3 --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-enable-winrt-app-revision.py @@ -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. + +""" +Make sure msvs_application_type_revision works correctly. +""" + +from __future__ import print_function + +import TestGyp + +import os +import sys + +CHDIR = 'winrt-app-type-revision' + +if sys.platform != 'win32' and os.environ.get('GYP_MSVS_VERSION', '0') < '2013': + print('Only for Windows') + sys.exit(2) + +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 --git a/tools/gyp/test/win/gyptest-link-enable-winrt-target-platform-version.py b/tools/gyp/test/win/gyptest-link-enable-winrt-target-platform-version.py new file mode 100644 index 00000000000000..babedf01551d65 --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-enable-winrt-target-platform-version.py @@ -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. + +""" +Make sure msvs_target_platform_version works correctly. +""" + +from __future__ import print_function + +import TestGyp + +import os +import sys +import struct + +CHDIR = 'winrt-target-platform-version' + + +if sys.platform != 'win32' and os.environ.get('GYP_MSVS_VERSION', '0') < '2015': + print('Only for Windows') + sys.exit(2) + +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 --git a/tools/gyp/test/win/gyptest-link-enable-winrt.py b/tools/gyp/test/win/gyptest-link-enable-winrt.py new file mode 100644 index 00000000000000..f964fa1f876a22 --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-enable-winrt.py @@ -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. +""" + +from __future__ import print_function + +import TestGyp + +import os +import sys +import struct + +CHDIR = 'enable-winrt' + +if sys.platform != 'win32' and os.environ.get('GYP_MSVS_VERSION', '0') < '2013': + print('Only for Windows') + sys.exit(2) + +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 --git a/tools/gyp/test/win/gyptest-link-entrypointsymbol.py b/tools/gyp/test/win/gyptest-link-entrypointsymbol.py new file mode 100644 index 00000000000000..e88174a0858054 --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-entrypointsymbol.py @@ -0,0 +1,24 @@ +#!/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. + +""" +Make sure entrypointsymbol setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('entrypointsymbol.gyp', chdir=CHDIR) + + test.build('entrypointsymbol.gyp', 'test_ok', chdir=CHDIR) + test.build('entrypointsymbol.gyp', 'test_fail', chdir=CHDIR, status=1) + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-link-fixed-base.py b/tools/gyp/test/win/gyptest-link-fixed-base.py new file mode 100644 index 00000000000000..725a87028a5669 --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-fixed-base.py @@ -0,0 +1,40 @@ +#!/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. + +""" +Make sure fixed base setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('fixed-base.gyp', chdir=CHDIR) + test.build('fixed-base.gyp', test.ALL, chdir=CHDIR) + + def GetHeaders(exe): + full_path = test.built_file_path(exe, chdir=CHDIR) + return test.run_dumpbin('/headers', full_path) + + # For exe, default is fixed, for dll, it's not fixed. + if 'Relocations stripped' not in GetHeaders('test_fixed_default_exe.exe'): + test.fail_test() + if 'Relocations stripped' in GetHeaders('test_fixed_default_dll.dll'): + test.fail_test() + + # Explicitly not fixed. + if 'Relocations stripped' in GetHeaders('test_fixed_no.exe'): + test.fail_test() + + # Explicitly fixed. + if 'Relocations stripped' not in GetHeaders('test_fixed_yes.exe'): + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-link-force-symbol-reference.py b/tools/gyp/test/win/gyptest-link-force-symbol-reference.py new file mode 100644 index 00000000000000..235e94f71bd3d5 --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-force-symbol-reference.py @@ -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 --git a/tools/gyp/test/win/gyptest-link-generate-manifest.py b/tools/gyp/test/win/gyptest-link-generate-manifest.py new file mode 100644 index 00000000000000..5cea15a570a739 --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-generate-manifest.py @@ -0,0 +1,94 @@ +""" +Make sure we generate a manifest file when linking binaries, including +handling AdditionalManifestFiles. +""" + +import TestGyp + +import sys + +if not sys.platform == 'win32': + print('Only for Windows') + sys.exit(2) + +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) + +# 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 --git a/tools/gyp/test/win/gyptest-link-incremental.py b/tools/gyp/test/win/gyptest-link-incremental.py new file mode 100644 index 00000000000000..e7184e162c8c10 --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-incremental.py @@ -0,0 +1,37 @@ +#!/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. + +""" +Make sure incremental linking setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('incremental.gyp', chdir=CHDIR) + test.build('incremental.gyp', test.ALL, chdir=CHDIR) + + def HasILTTables(exe): + full_path = test.built_file_path(exe, chdir=CHDIR) + output = test.run_dumpbin('/disasm', full_path) + return '@ILT+' in output + + # Default or unset is to be on. + if not HasILTTables('test_incremental_unset.exe'): + test.fail_test() + if not HasILTTables('test_incremental_default.exe'): + test.fail_test() + if HasILTTables('test_incremental_no.exe'): + test.fail_test() + if not HasILTTables('test_incremental_yes.exe'): + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-link-large-address-aware.py b/tools/gyp/test/win/gyptest-link-large-address-aware.py new file mode 100644 index 00000000000000..ea433f20994cfc --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-large-address-aware.py @@ -0,0 +1,35 @@ +#!/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. + +""" +Make sure largeaddressaware setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('large-address-aware.gyp', chdir=CHDIR) + test.build('large-address-aware.gyp', test.ALL, chdir=CHDIR) + + def GetHeaders(exe): + return test.run_dumpbin('/headers', test.built_file_path(exe, chdir=CHDIR)) + + MARKER = 'Application can handle large (>2GB) addresses' + + # Explicitly off. + if MARKER in GetHeaders('test_large_address_aware_no.exe'): + test.fail_test() + + # Explicitly on. + if MARKER not in GetHeaders('test_large_address_aware_yes.exe'): + test.fail_test() + + test.pass_test() diff --git a/tools/gyp/test/win/gyptest-link-large-pdb.py b/tools/gyp/test/win/gyptest-link-large-pdb.py new file mode 100644 index 00000000000000..1fb27b0ab716df --- /dev/null +++ b/tools/gyp/test/win/gyptest-link-large-pdb.py @@ -0,0 +1,76 @@ +#!/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_large_pdb works correctly. +""" + +from __future__ import print_function + +import TestGyp + +import struct +import sys + +if sys.platform == 'win32': + print("This test is currently disabled: https://crbug.com/483696.") + sys.exit(0) + + +CHDIR = 'large-pdb' + + +def CheckImageAndPdb(test, image_basename, expected_page_size, + pdb_basename=None): + if not pdb_basename: + pdb_basename = image_basename + '.pdb' + test.built_file_must_exist(image_basename, chdir=CHDIR) + test.built_file_must_exist(pdb_basename, chdir=CHDIR) + + # We expect the PDB to have the given page size. For full details of the + # header look here: https://code.google.com/p/pdbparser/wiki/MSF_Format + # We read the little-endian 4-byte unsigned integer at position 32 of the + # file. + pdb_path = test.built_file_path(pdb_basename, chdir=CHDIR) + pdb_file = open(pdb_path, 'rb') + pdb_file.seek(32, 0) + page_size = struct.unpack('(indexer)); + return 0; +} diff --git a/tools/gyp/test/win/idl-rules/idl_compiler.py b/tools/gyp/test/win/idl-rules/idl_compiler.py new file mode 100644 index 00000000000000..a12b274d6754c4 --- /dev/null +++ b/tools/gyp/test/win/idl-rules/idl_compiler.py @@ -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 --git a/tools/gyp/test/win/importlib/dll_no_exports.cc b/tools/gyp/test/win/importlib/dll_no_exports.cc new file mode 100644 index 00000000000000..96dd7970b71450 --- /dev/null +++ b/tools/gyp/test/win/importlib/dll_no_exports.cc @@ -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 --git a/tools/gyp/test/win/importlib/has-exports.cc b/tools/gyp/test/win/importlib/has-exports.cc new file mode 100644 index 00000000000000..3f62d6c60de6a4 --- /dev/null +++ b/tools/gyp/test/win/importlib/has-exports.cc @@ -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. + +__declspec(dllexport) void some_function() { +} + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/importlib/hello.cc b/tools/gyp/test/win/importlib/hello.cc new file mode 100644 index 00000000000000..66ff68c11314bd --- /dev/null +++ b/tools/gyp/test/win/importlib/hello.cc @@ -0,0 +1,9 @@ +// 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. + +__declspec(dllimport) void some_function(); + +int main() { + some_function(); +} diff --git a/tools/gyp/test/win/importlib/importlib.gyp b/tools/gyp/test/win/importlib/importlib.gyp new file mode 100644 index 00000000000000..ab15b1893d46c6 --- /dev/null +++ b/tools/gyp/test/win/importlib/importlib.gyp @@ -0,0 +1,30 @@ +# 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_importlib', + 'type': 'shared_library', + 'msvs_settings': { + 'VCLinkerTool': { + 'LinkIncremental': '2', + } + }, + 'sources': ['has-exports.cc'], + }, + + { + 'target_name': 'test_linkagainst', + 'type': 'executable', + 'dependencies': ['test_importlib'], + 'msvs_settings': { + 'VCLinkerTool': { + 'LinkIncremental': '2', + } + }, + 'sources': ['hello.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/importlib/noimplib.gyp b/tools/gyp/test/win/importlib/noimplib.gyp new file mode 100644 index 00000000000000..0245058a996b48 --- /dev/null +++ b/tools/gyp/test/win/importlib/noimplib.gyp @@ -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 --git a/tools/gyp/test/win/large-pdb/dllmain.cc b/tools/gyp/test/win/large-pdb/dllmain.cc new file mode 100644 index 00000000000000..14875623e833b6 --- /dev/null +++ b/tools/gyp/test/win/large-pdb/dllmain.cc @@ -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. + +#include + +BOOL WINAPI DllMain(HINSTANCE hinstance, DWORD reason, LPVOID reserved) { + return TRUE; +} diff --git a/tools/gyp/test/win/large-pdb/large-pdb.gyp b/tools/gyp/test/win/large-pdb/large-pdb.gyp new file mode 100644 index 00000000000000..2a241a56233184 --- /dev/null +++ b/tools/gyp/test/win/large-pdb/large-pdb.gyp @@ -0,0 +1,98 @@ +# 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': 'large_pdb_exe', + 'type': 'executable', + 'msvs_large_pdb': 1, + 'sources': [ + 'main.cc', + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'ProgramDatabaseFile': '<(PRODUCT_DIR)/large_pdb_exe.exe.pdb', + }, + }, + }, + { + 'target_name': 'small_pdb_exe', + 'type': 'executable', + 'msvs_large_pdb': 0, + 'sources': [ + 'main.cc', + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'ProgramDatabaseFile': '<(PRODUCT_DIR)/small_pdb_exe.exe.pdb', + }, + }, + }, + { + 'target_name': 'large_pdb_dll', + 'type': 'shared_library', + 'msvs_large_pdb': 1, + 'sources': [ + 'dllmain.cc', + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'ProgramDatabaseFile': '<(PRODUCT_DIR)/large_pdb_dll.dll.pdb', + }, + }, + }, + { + 'target_name': 'small_pdb_dll', + 'type': 'shared_library', + 'msvs_large_pdb': 0, + 'sources': [ + 'dllmain.cc', + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'ProgramDatabaseFile': '<(PRODUCT_DIR)/small_pdb_dll.dll.pdb', + }, + }, + }, + { + 'target_name': 'large_pdb_implicit_exe', + 'type': 'executable', + 'msvs_large_pdb': 1, + 'sources': [ + 'main.cc', + ], + # No PDB file is specified. However, the msvs_large_pdb mechanism should + # default to the appropriate <(PRODUCT_DIR)/<(TARGET_NAME).exe.pdb. + }, + { + 'target_name': 'large_pdb_variable_exe', + 'type': 'executable', + 'msvs_large_pdb': 1, + 'sources': [ + 'main.cc', + ], + # No PDB file is specified. However, the msvs_large_pdb_path variable + # explicitly sets one. + 'variables': { + 'msvs_large_pdb_path': '<(PRODUCT_DIR)/foo.pdb', + }, + }, + { + 'target_name': 'large_pdb_product_exe', + 'product_name': 'bar', + 'type': 'executable', + 'msvs_large_pdb': 1, + 'sources': [ + 'main.cc', + ], + # No PDB file is specified. However, we've specified a product name so + # it should use <(PRODUCT_DIR)/bar.exe.pdb. + }, + ] +} diff --git a/tools/gyp/test/win/large-pdb/main.cc b/tools/gyp/test/win/large-pdb/main.cc new file mode 100644 index 00000000000000..c3da8e92193056 --- /dev/null +++ b/tools/gyp/test/win/large-pdb/main.cc @@ -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(void) { + return 0; +} diff --git a/tools/gyp/test/win/lib-crosscompile/answer.cc b/tools/gyp/test/win/lib-crosscompile/answer.cc new file mode 100644 index 00000000000000..a6ffa168620f58 --- /dev/null +++ b/tools/gyp/test/win/lib-crosscompile/answer.cc @@ -0,0 +1,9 @@ +// 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 "answer.h" + +int answer() { + return 42; +} diff --git a/tools/gyp/test/win/lib-crosscompile/answer.h b/tools/gyp/test/win/lib-crosscompile/answer.h new file mode 100644 index 00000000000000..82312d54b8e7b0 --- /dev/null +++ b/tools/gyp/test/win/lib-crosscompile/answer.h @@ -0,0 +1,5 @@ +// 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. + +int answer(); \ No newline at end of file diff --git a/tools/gyp/test/win/lib-crosscompile/use_host_ar.gyp b/tools/gyp/test/win/lib-crosscompile/use_host_ar.gyp new file mode 100644 index 00000000000000..4747bc6445566d --- /dev/null +++ b/tools/gyp/test/win/lib-crosscompile/use_host_ar.gyp @@ -0,0 +1,17 @@ +# Copyright (c) 2015 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': 'lib_answer', + 'type': 'static_library', + 'toolsets': ['host'], + 'msvs_settings': { + 'msvs_cygwin_shell': 0, + }, + 'sources': ['answer.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/lib-flags/answer.cc b/tools/gyp/test/win/lib-flags/answer.cc new file mode 100644 index 00000000000000..a6ffa168620f58 --- /dev/null +++ b/tools/gyp/test/win/lib-flags/answer.cc @@ -0,0 +1,9 @@ +// 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 "answer.h" + +int answer() { + return 42; +} diff --git a/tools/gyp/test/win/lib-flags/answer.h b/tools/gyp/test/win/lib-flags/answer.h new file mode 100644 index 00000000000000..82312d54b8e7b0 --- /dev/null +++ b/tools/gyp/test/win/lib-flags/answer.h @@ -0,0 +1,5 @@ +// 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. + +int answer(); \ No newline at end of file diff --git a/tools/gyp/test/win/lib-flags/ltcg.gyp b/tools/gyp/test/win/lib-flags/ltcg.gyp new file mode 100644 index 00000000000000..c183107730ad2c --- /dev/null +++ b/tools/gyp/test/win/lib-flags/ltcg.gyp @@ -0,0 +1,21 @@ +# 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': 'lib_answer', + 'type': 'static_library', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WholeProgramOptimization': 'true', # /GL + }, + 'VCLibrarianTool': { + 'LinkTimeCodeGeneration': 'true', # /LTCG + }, + }, + 'sources': ['answer.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/a/x.cc b/tools/gyp/test/win/linker-flags/a/x.cc new file mode 100644 index 00000000000000..f5f763b0956348 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/a/x.cc @@ -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 --git a/tools/gyp/test/win/linker-flags/a/z.cc b/tools/gyp/test/win/linker-flags/a/z.cc new file mode 100644 index 00000000000000..8a43501270ae8a --- /dev/null +++ b/tools/gyp/test/win/linker-flags/a/z.cc @@ -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 --git a/tools/gyp/test/win/linker-flags/additional-deps.cc b/tools/gyp/test/win/linker-flags/additional-deps.cc new file mode 100644 index 00000000000000..7dfb589d26d198 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/additional-deps.cc @@ -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() { + WSAStartup(0, 0); + return 0; +} diff --git a/tools/gyp/test/win/linker-flags/additional-deps.gyp b/tools/gyp/test/win/linker-flags/additional-deps.gyp new file mode 100644 index 00000000000000..55afe64fb09466 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/additional-deps.gyp @@ -0,0 +1,30 @@ +# 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_deps_none', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_deps_few', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'AdditionalDependencies': [ + 'wininet.lib', + 'ws2_32.lib', + ] + } + }, + 'sources': ['additional-deps.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/additional-options.gyp b/tools/gyp/test/win/linker-flags/additional-options.gyp new file mode 100644 index 00000000000000..be47a6b04e2156 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/additional-options.gyp @@ -0,0 +1,29 @@ +# 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_additional_none', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_additional_few', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'AdditionalOptions': [ + '/dynamicbase:no', + ] + } + }, + 'sources': ['hello.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/aslr.gyp b/tools/gyp/test/win/linker-flags/aslr.gyp new file mode 100644 index 00000000000000..b3aefd50b7f0c4 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/aslr.gyp @@ -0,0 +1,35 @@ +# 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_aslr_default', + 'type': 'executable', + 'msvs_settings': { + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_aslr_no', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'RandomizedBaseAddress': '1', + }, + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_aslr_yes', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'RandomizedBaseAddress': '2', + } + }, + 'sources': ['hello.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/b/y.cc b/tools/gyp/test/win/linker-flags/b/y.cc new file mode 100644 index 00000000000000..bd884119fcd44a --- /dev/null +++ b/tools/gyp/test/win/linker-flags/b/y.cc @@ -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 --git a/tools/gyp/test/win/linker-flags/base-address.gyp b/tools/gyp/test/win/linker-flags/base-address.gyp new file mode 100644 index 00000000000000..873ebfea3f124e --- /dev/null +++ b/tools/gyp/test/win/linker-flags/base-address.gyp @@ -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 --git a/tools/gyp/test/win/linker-flags/debug-info.gyp b/tools/gyp/test/win/linker-flags/debug-info.gyp new file mode 100644 index 00000000000000..d47d0ecced958a --- /dev/null +++ b/tools/gyp/test/win/linker-flags/debug-info.gyp @@ -0,0 +1,28 @@ +# 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_debug_off', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'GenerateDebugInformation': 'false' + }, + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_debug_on', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true' + }, + }, + 'sources': ['hello.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/deffile-multiple.gyp b/tools/gyp/test/win/linker-flags/deffile-multiple.gyp new file mode 100644 index 00000000000000..c74a9af20aecc3 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/deffile-multiple.gyp @@ -0,0 +1,17 @@ +# 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_deffile_multiple_fail', + 'type': 'shared_library', + 'sources': [ + 'deffile.cc', + 'deffile.def', + 'deffile2.def', + ], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/deffile.cc b/tools/gyp/test/win/linker-flags/deffile.cc new file mode 100644 index 00000000000000..fa203b34c84e1e --- /dev/null +++ b/tools/gyp/test/win/linker-flags/deffile.cc @@ -0,0 +1,13 @@ +// 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. + +void AnExportedFunction() { +} + +void AnotherExportedFunction() { +} + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/linker-flags/deffile.def b/tools/gyp/test/win/linker-flags/deffile.def new file mode 100644 index 00000000000000..ba9d399bd6f9ae --- /dev/null +++ b/tools/gyp/test/win/linker-flags/deffile.def @@ -0,0 +1,8 @@ +; 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. + +LIBRARY test_deffile_ok + +EXPORTS + AnExportedFunction diff --git a/tools/gyp/test/win/linker-flags/deffile.gyp b/tools/gyp/test/win/linker-flags/deffile.gyp new file mode 100644 index 00000000000000..7b241d5e3ae45a --- /dev/null +++ b/tools/gyp/test/win/linker-flags/deffile.gyp @@ -0,0 +1,38 @@ +# 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_deffile_dll_ok', + 'type': 'shared_library', + 'sources': [ + 'deffile.cc', + 'deffile.def', + ], + }, + { + 'target_name': 'test_deffile_dll_notexported', + 'type': 'shared_library', + 'sources': [ + 'deffile.cc', + ], + }, + { + 'target_name': 'test_deffile_exe_ok', + 'type': 'executable', + 'sources': [ + 'deffile.cc', + 'deffile.def', + ], + }, + { + 'target_name': 'test_deffile_exe_notexported', + 'type': 'executable', + 'sources': [ + 'deffile.cc', + ], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/delay-load-dlls.gyp b/tools/gyp/test/win/linker-flags/delay-load-dlls.gyp new file mode 100644 index 00000000000000..671cbaa802f536 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/delay-load-dlls.gyp @@ -0,0 +1,35 @@ +# 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_dld_none', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + } + }, + 'sources': ['delay-load.cc'], + 'libraries': [ + 'delayimp.lib', + 'shell32.lib', + ], + }, + { + 'target_name': 'test_dld_shell32', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'DelayLoadDLLs': ['shell32.dll'] + } + }, + 'sources': ['delay-load.cc'], + 'libraries': [ + 'delayimp.lib', + 'shell32.lib', + ], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/delay-load.cc b/tools/gyp/test/win/linker-flags/delay-load.cc new file mode 100644 index 00000000000000..2be34aa876c79a --- /dev/null +++ b/tools/gyp/test/win/linker-flags/delay-load.cc @@ -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() { + SHCreateDirectory(0, 0); + return 0; +} diff --git a/tools/gyp/test/win/linker-flags/embed-manifest.gyp b/tools/gyp/test/win/linker-flags/embed-manifest.gyp new file mode 100644 index 00000000000000..fefb2f56d85e2a --- /dev/null +++ b/tools/gyp/test/win/linker-flags/embed-manifest.gyp @@ -0,0 +1,109 @@ +# Copyright (c) 2013 Yandex LLC. 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': { + 'VCLinkerTool': { + 'LinkIncremental': '1', + }, + 'VCManifestTool': { + 'EmbedManifest': 'true', + } + }, + }, + { + 'target_name': 'test_manifest_dll', + 'type': 'loadable_module', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'LinkIncremental': '1', + }, + 'VCManifestTool': { + 'EmbedManifest': 'true', + } + }, + }, + { + 'target_name': 'test_manifest_extra1', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCManifestTool': { + 'EmbedManifest': 'true', + 'AdditionalManifestFiles': 'extra.manifest', + } + }, + }, + { + 'target_name': 'test_manifest_extra2', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCManifestTool': { + 'EmbedManifest': 'true', + 'AdditionalManifestFiles': 'extra.manifest;extra2.manifest', + } + }, + }, + { + 'target_name': 'test_manifest_extra_list', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCManifestTool': { + 'EmbedManifest': 'true', + 'AdditionalManifestFiles': [ + 'extra.manifest', + 'extra2.manifest' + ], + } + }, + }, + { + 'target_name': 'test_manifest_dll_inc', + 'type': 'loadable_module', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'LinkIncremental': '2', + }, + 'VCManifestTool': { + 'EmbedManifest': 'true', + } + }, + }, + { + 'target_name': 'test_manifest_exe_inc', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'LinkIncremental': '2', + }, + 'VCManifestTool': { + 'EmbedManifest': 'true', + } + }, + }, + { + 'target_name': 'test_manifest_exe_inc_no_embed', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'LinkIncremental': '2', + }, + 'VCManifestTool': { + 'EmbedManifest': 'false', + } + }, + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/enable-uac.gyp b/tools/gyp/test/win/linker-flags/enable-uac.gyp new file mode 100644 index 00000000000000..4e58c86ec88550 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/enable-uac.gyp @@ -0,0 +1,45 @@ +# 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': 'enable_uac', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCManifestTool': { + 'EmbedManifest': 'true', + } + }, + }, + { + 'target_name': 'enable_uac_no', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'EnableUAC': 'false', + }, + 'VCManifestTool': { + 'EmbedManifest': 'true', + } + }, + }, + { + 'target_name': 'enable_uac_admin', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'UACExecutionLevel': 2, + 'UACUIAccess': 'true', + }, + 'VCManifestTool': { + 'EmbedManifest': 'true', + } + }, + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/entrypointsymbol.cc b/tools/gyp/test/win/linker-flags/entrypointsymbol.cc new file mode 100644 index 00000000000000..b567bc87b30bca --- /dev/null +++ b/tools/gyp/test/win/linker-flags/entrypointsymbol.cc @@ -0,0 +1,13 @@ +// 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. + +// The entry point specified by link.exe /ENTRY option. +extern "C" void MainEntryPoint() { +} + +// Still needed because the linker checks for existence of one of main, wmain, +// WinMain, or wMain to offer informative diagnositics. +int main() { + return 0; +} diff --git a/tools/gyp/test/win/linker-flags/entrypointsymbol.gyp b/tools/gyp/test/win/linker-flags/entrypointsymbol.gyp new file mode 100644 index 00000000000000..7f2c14252d013e --- /dev/null +++ b/tools/gyp/test/win/linker-flags/entrypointsymbol.gyp @@ -0,0 +1,28 @@ +# 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_ok', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'EntryPointSymbol': 'MainEntryPoint', + } + }, + 'sources': ['entrypointsymbol.cc'], + }, + { + 'target_name': 'test_fail', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'EntryPointSymbol': 'MainEntryPoint', + } + }, + 'sources': ['hello.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/extra.manifest b/tools/gyp/test/win/linker-flags/extra.manifest new file mode 100644 index 00000000000000..64d49cd0a8c766 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/extra.manifest @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/gyp/test/win/linker-flags/extra2.manifest b/tools/gyp/test/win/linker-flags/extra2.manifest new file mode 100644 index 00000000000000..246c15da7ef1a2 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/extra2.manifest @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tools/gyp/test/win/linker-flags/fixed-base.gyp b/tools/gyp/test/win/linker-flags/fixed-base.gyp new file mode 100644 index 00000000000000..cc2982eb2799cb --- /dev/null +++ b/tools/gyp/test/win/linker-flags/fixed-base.gyp @@ -0,0 +1,52 @@ +# 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': [ + # Disable DYNAMICBASE for these tests because it implies/doesn't imply + # FIXED in certain cases so it complicates the test for FIXED. + { + 'target_name': 'test_fixed_default_exe', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'RandomizedBaseAddress': '1', + }, + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_fixed_default_dll', + 'type': 'shared_library', + 'msvs_settings': { + 'VCLinkerTool': { + 'RandomizedBaseAddress': '1', + }, + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_fixed_no', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'FixedBaseAddress': '1', + 'RandomizedBaseAddress': '1', + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_fixed_yes', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'FixedBaseAddress': '2', + 'RandomizedBaseAddress': '1', + }, + }, + 'sources': ['hello.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/force-symbol-reference.gyp b/tools/gyp/test/win/linker-flags/force-symbol-reference.gyp new file mode 100644 index 00000000000000..1f354fafc7b78c --- /dev/null +++ b/tools/gyp/test/win/linker-flags/force-symbol-reference.gyp @@ -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 --git a/tools/gyp/test/win/linker-flags/generate-manifest.gyp b/tools/gyp/test/win/linker-flags/generate-manifest.gyp new file mode 100644 index 00000000000000..34a68d1a489db7 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/generate-manifest.gyp @@ -0,0 +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_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 --git a/tools/gyp/test/win/linker-flags/hello.cc b/tools/gyp/test/win/linker-flags/hello.cc new file mode 100644 index 00000000000000..1711567ef56670 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/hello.cc @@ -0,0 +1,7 @@ +// 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. + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/linker-flags/incremental.gyp b/tools/gyp/test/win/linker-flags/incremental.gyp new file mode 100644 index 00000000000000..59f3103253ce83 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/incremental.gyp @@ -0,0 +1,65 @@ +# 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': [ + # Turn on debug information so the incremental linking tables have a + # visible symbolic name in the disassembly. + { + 'target_name': 'test_incremental_unset', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + }, + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_incremental_default', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'LinkIncremental': '0', + }, + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_incremental_no', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'LinkIncremental': '1', + }, + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_incremental_yes', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'LinkIncremental': '2', + } + }, + 'sources': ['hello.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/inline_test.cc b/tools/gyp/test/win/linker-flags/inline_test.cc new file mode 100644 index 00000000000000..a9f177e4768a29 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/inline_test.cc @@ -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 --git a/tools/gyp/test/win/linker-flags/inline_test.h b/tools/gyp/test/win/linker-flags/inline_test.h new file mode 100644 index 00000000000000..117913c4f50403 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/inline_test.h @@ -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 --git a/tools/gyp/test/win/linker-flags/inline_test_main.cc b/tools/gyp/test/win/linker-flags/inline_test_main.cc new file mode 100644 index 00000000000000..23cafe8f94a3bc --- /dev/null +++ b/tools/gyp/test/win/linker-flags/inline_test_main.cc @@ -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 --git a/tools/gyp/test/win/linker-flags/large-address-aware.gyp b/tools/gyp/test/win/linker-flags/large-address-aware.gyp new file mode 100644 index 00000000000000..fa56d3789ce318 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/large-address-aware.gyp @@ -0,0 +1,28 @@ +# 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_large_address_aware_no', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'LargeAddressAware': '1', + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_large_address_aware_yes', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'LargeAddressAware': '2', + }, + }, + 'sources': ['hello.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/library-adjust.cc b/tools/gyp/test/win/linker-flags/library-adjust.cc new file mode 100644 index 00000000000000..7dfb589d26d198 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/library-adjust.cc @@ -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() { + WSAStartup(0, 0); + return 0; +} diff --git a/tools/gyp/test/win/linker-flags/library-adjust.gyp b/tools/gyp/test/win/linker-flags/library-adjust.gyp new file mode 100644 index 00000000000000..10e9996f5c6a8c --- /dev/null +++ b/tools/gyp/test/win/linker-flags/library-adjust.gyp @@ -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': 'test_adjust', + 'type': 'executable', + 'libraries': [ + '-lws2_32.lib' + ], + 'sources': ['library-adjust.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/library-directories-define.cc b/tools/gyp/test/win/linker-flags/library-directories-define.cc new file mode 100644 index 00000000000000..211ef062c1390a --- /dev/null +++ b/tools/gyp/test/win/linker-flags/library-directories-define.cc @@ -0,0 +1,7 @@ +// 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. + +int library_function() { + return 0; +} diff --git a/tools/gyp/test/win/linker-flags/library-directories-reference.cc b/tools/gyp/test/win/linker-flags/library-directories-reference.cc new file mode 100644 index 00000000000000..335097839a18b8 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/library-directories-reference.cc @@ -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. + +extern int library_function(); + +int main() { + library_function(); + return 0; +} diff --git a/tools/gyp/test/win/linker-flags/library-directories.gyp b/tools/gyp/test/win/linker-flags/library-directories.gyp new file mode 100644 index 00000000000000..25395d6c879de4 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/library-directories.gyp @@ -0,0 +1,42 @@ +# 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_libdirs_none', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'AdditionalDependencies': [ + 'test_lib.lib', + ], + }, + }, + 'sources': ['library-directories-reference.cc'], + }, + { + 'target_name': 'test_libdirs_with', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + # NOTE: Don't use this for general dependencies between gyp + # libraries (use 'dependencies' instead). This is done here only for + # testing. + # + # This setting should only be used to depend on third party prebuilt + # libraries that are stored as binaries at a known location. + 'AdditionalLibraryDirectories': [ + '<(DEPTH)/out/Default/obj/subdir', # ninja style + '<(DEPTH)/subdir/Default/lib', # msvs style + ], + 'AdditionalDependencies': [ + 'test_lib.lib', + ], + }, + }, + 'sources': ['library-directories-reference.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/link-ordering.gyp b/tools/gyp/test/win/linker-flags/link-ordering.gyp new file mode 100644 index 00000000000000..66f44309d1388b --- /dev/null +++ b/tools/gyp/test/win/linker-flags/link-ordering.gyp @@ -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 --git a/tools/gyp/test/win/linker-flags/link-warning.cc b/tools/gyp/test/win/linker-flags/link-warning.cc new file mode 100644 index 00000000000000..4b34277ba35ace --- /dev/null +++ b/tools/gyp/test/win/linker-flags/link-warning.cc @@ -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 --git a/tools/gyp/test/win/linker-flags/ltcg.gyp b/tools/gyp/test/win/linker-flags/ltcg.gyp new file mode 100644 index 00000000000000..ddb0d9b4e2b590 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/ltcg.gyp @@ -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 --git a/tools/gyp/test/win/linker-flags/main-crt.c b/tools/gyp/test/win/linker-flags/main-crt.c new file mode 100644 index 00000000000000..bdc80c54fd9532 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/main-crt.c @@ -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 --git a/tools/gyp/test/win/linker-flags/manifest-in-comment.cc b/tools/gyp/test/win/linker-flags/manifest-in-comment.cc new file mode 100644 index 00000000000000..ae54ae54629000 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/manifest-in-comment.cc @@ -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 --git a/tools/gyp/test/win/linker-flags/mapfile.cc b/tools/gyp/test/win/linker-flags/mapfile.cc new file mode 100644 index 00000000000000..cebccb264a0631 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/mapfile.cc @@ -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. + +__declspec(dllexport) +void AnExportedFunction() { + // We need an exported function to verify that /MAPINFO:EXPORTS works. +} + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/linker-flags/mapfile.gyp b/tools/gyp/test/win/linker-flags/mapfile.gyp new file mode 100644 index 00000000000000..14206fe28d7d28 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/mapfile.gyp @@ -0,0 +1,45 @@ +# 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_mapfile_unset', + 'type': 'executable', + 'sources': ['mapfile.cc'], + }, + { + 'target_name': 'test_mapfile_generate', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'GenerateMapFile': 'true', + }, + }, + 'sources': ['mapfile.cc'], + }, + { + 'target_name': 'test_mapfile_generate_exports', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'GenerateMapFile': 'true', + 'MapExports': 'true', + }, + }, + 'sources': ['mapfile.cc'], + }, + { + 'target_name': 'test_mapfile_generate_filename', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'GenerateMapFile': 'true', + 'MapFileName': '<(PRODUCT_DIR)/custom_file_name.map', + }, + }, + 'sources': ['mapfile.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/no-default-libs.cc b/tools/gyp/test/win/linker-flags/no-default-libs.cc new file mode 100644 index 00000000000000..e306846987d378 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/no-default-libs.cc @@ -0,0 +1,18 @@ +// 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. + +// Reference something in kernel32.dll. This will fail to link, verifying that +// GYP provides no default import library configuration. +// Note that we don't include Windows.h, as that will result in generating +// linker directives in the object file through #pragma comment(lib, ...). +typedef short BOOL; + +extern "C" __declspec(dllimport) +BOOL CopyFileW(const wchar_t*, const wchar_t*, BOOL); + + +int main() { + CopyFileW(0, 0, 0); // kernel32 + return 0; +} diff --git a/tools/gyp/test/win/linker-flags/no-default-libs.gyp b/tools/gyp/test/win/linker-flags/no-default-libs.gyp new file mode 100644 index 00000000000000..77838ce8c4c617 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/no-default-libs.gyp @@ -0,0 +1,13 @@ +# 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_default', + 'type': 'executable', + 'sources': ['no-default-libs.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/nodefaultlib.cc b/tools/gyp/test/win/linker-flags/nodefaultlib.cc new file mode 100644 index 00000000000000..24b6eca438fe8a --- /dev/null +++ b/tools/gyp/test/win/linker-flags/nodefaultlib.cc @@ -0,0 +1,13 @@ +// 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 entry point function that's excluded by removing C runtime libraries. +extern "C" void mainCRTStartup() { +} + +// Still needed because the linker checks for existence of one of main, wmain, +// WinMain, or wMain to offer informative diagnositics. +int main() { + return 0; +} diff --git a/tools/gyp/test/win/linker-flags/nodefaultlib.gyp b/tools/gyp/test/win/linker-flags/nodefaultlib.gyp new file mode 100644 index 00000000000000..4fb452a18bcafb --- /dev/null +++ b/tools/gyp/test/win/linker-flags/nodefaultlib.gyp @@ -0,0 +1,30 @@ +# 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_ok', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'IgnoreDefaultLibraryNames': + ['libcmtd.lib', 'libcmt.lib', 'msvcrt.lib', 'msvcrtd.lib'], + } + }, + 'sources': ['nodefaultlib.cc'], + }, + { + 'target_name': 'test_fail', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'IgnoreDefaultLibraryNames': + ['libcmtd.lib', 'libcmt.lib', 'msvcrt.lib', 'msvcrtd.lib'], + } + }, + 'sources': ['hello.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/nxcompat.gyp b/tools/gyp/test/win/linker-flags/nxcompat.gyp new file mode 100644 index 00000000000000..fa4118cbd73ebc --- /dev/null +++ b/tools/gyp/test/win/linker-flags/nxcompat.gyp @@ -0,0 +1,35 @@ +# 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_nxcompat_default', + 'type': 'executable', + 'msvs_settings': { + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_nxcompat_no', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'DataExecutionPrevention': '1', + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_nxcompat_yes', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'DataExecutionPrevention': '2', + }, + }, + 'sources': ['hello.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/opt-icf.cc b/tools/gyp/test/win/linker-flags/opt-icf.cc new file mode 100644 index 00000000000000..1f12156b7fc37c --- /dev/null +++ b/tools/gyp/test/win/linker-flags/opt-icf.cc @@ -0,0 +1,29 @@ +// 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. + +void similar_function0(char* x) { + while (*x) { + ++x; + } +} + +void similar_function1(char* p) { + while (*p) { + ++p; + } +} + +void similar_function2(char* q) { + while (*q) { + ++q; + } +} + +int main() { + char* x = "hello"; + similar_function0(x); + similar_function1(x); + similar_function2(x); + return 0; +} diff --git a/tools/gyp/test/win/linker-flags/opt-icf.gyp b/tools/gyp/test/win/linker-flags/opt-icf.gyp new file mode 100644 index 00000000000000..effe8021c34273 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/opt-icf.gyp @@ -0,0 +1,63 @@ +# 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': [ + # Have to turn on function level linking here to get the function packaged + # as a COMDAT so that it's eligible for merging. Also turn on debug + # information so that the symbol names for the code appear in the dump. + # Finally, specify non-incremental linking so that there's not a bunch of + # extra "similar_function"s in the output (the ILT jump table). + { + 'target_name': 'test_opticf_default', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableFunctionLevelLinking': 'true', + 'DebugInformationFormat': '3', + 'Optimization': '0', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'LinkIncremental': '1', + }, + }, + 'sources': ['opt-icf.cc'], + }, + { + 'target_name': 'test_opticf_no', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableFunctionLevelLinking': 'true', + 'DebugInformationFormat': '3', + 'Optimization': '0', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'EnableCOMDATFolding': '1', + 'LinkIncremental': '1', + }, + }, + 'sources': ['opt-icf.cc'], + }, + { + 'target_name': 'test_opticf_yes', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableFunctionLevelLinking': 'true', + 'DebugInformationFormat': '3', + 'Optimization': '0', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'EnableCOMDATFolding': '2', + 'LinkIncremental': '1', + }, + }, + 'sources': ['opt-icf.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/opt-ref.cc b/tools/gyp/test/win/linker-flags/opt-ref.cc new file mode 100644 index 00000000000000..afaa328a5d571a --- /dev/null +++ b/tools/gyp/test/win/linker-flags/opt-ref.cc @@ -0,0 +1,11 @@ +// 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. + +int unused_function() { + return 0; +} + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/linker-flags/opt-ref.gyp b/tools/gyp/test/win/linker-flags/opt-ref.gyp new file mode 100644 index 00000000000000..69d0281a08d2e2 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/opt-ref.gyp @@ -0,0 +1,56 @@ +# 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': [ + # Have to turn on function level linking here to get the function packaged + # as a COMDAT so that it's eligible for optimizing away. Also turn on + # debug information so that the symbol names for the code appear in the + # dump (so we can verify if they are included in the final exe). + { + 'target_name': 'test_optref_default', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableFunctionLevelLinking': 'true', + 'DebugInformationFormat': '3', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + }, + }, + 'sources': ['opt-ref.cc'], + }, + { + 'target_name': 'test_optref_no', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableFunctionLevelLinking': 'true', + 'DebugInformationFormat': '3', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'OptimizeReferences': '1', + }, + }, + 'sources': ['opt-ref.cc'], + }, + { + 'target_name': 'test_optref_yes', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableFunctionLevelLinking': 'true', + 'DebugInformationFormat': '3', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'OptimizeReferences': '2', + }, + }, + 'sources': ['opt-ref.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/outputfile.gyp b/tools/gyp/test/win/linker-flags/outputfile.gyp new file mode 100644 index 00000000000000..1022ec2e20aaba --- /dev/null +++ b/tools/gyp/test/win/linker-flags/outputfile.gyp @@ -0,0 +1,58 @@ +# 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_output_exe', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(OutDir)\\blorp.exe' + }, + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_output_exe2', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(OutDir)\\subdir\\blorp.exe' + }, + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_output_dll', + 'type': 'shared_library', + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(OutDir)\\blorp.dll' + }, + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_output_lib', + 'type': 'static_library', + 'msvs_settings': { + 'VCLibrarianTool': { + 'OutputFile': '$(OutDir)\\blorp.lib' + }, + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_output_lib2', + 'type': 'static_library', + 'msvs_settings': { + 'VCLibrarianTool': { + 'OutputFile': '$(OutDir)\\subdir\\blorp.lib' + }, + }, + 'sources': ['hello.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/pdb-output.gyp b/tools/gyp/test/win/linker-flags/pdb-output.gyp new file mode 100644 index 00000000000000..1a03c67cc01c61 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/pdb-output.gyp @@ -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 --git a/tools/gyp/test/win/linker-flags/pgo.gyp b/tools/gyp/test/win/linker-flags/pgo.gyp new file mode 100644 index 00000000000000..9c5d4768839306 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/pgo.gyp @@ -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 --git a/tools/gyp/test/win/linker-flags/profile.gyp b/tools/gyp/test/win/linker-flags/profile.gyp new file mode 100644 index 00000000000000..d60a700fbbf293 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/profile.gyp @@ -0,0 +1,50 @@ +# 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': [ + # Verify that 'Profile' option correctly makes it to LINK steup in Ninja + { + 'target_name': 'test_profile_true', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3' + }, + 'VCLinkerTool': { + 'Profile': 'true', + 'GenerateDebugInformation': 'true', + }, + }, + }, + { + 'target_name': 'test_profile_false', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3' + }, + 'VCLinkerTool': { + 'Profile': 'false', + 'GenerateDebugInformation': 'true', + }, + }, + }, + { + 'target_name': 'test_profile_default', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3' + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + }, + }, + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/program-database.gyp b/tools/gyp/test/win/linker-flags/program-database.gyp new file mode 100644 index 00000000000000..6e60ac0dc99848 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/program-database.gyp @@ -0,0 +1,40 @@ +# 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': [ + # Verify that 'ProgramDatabaseFile' option correctly makes it to LINK + # step in Ninja. + { + # Verify that VC macros and windows paths work correctly. + 'target_name': 'test_pdb_outdir', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3' + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'ProgramDatabaseFile': '$(OutDir)\\name_outdir.pdb', + }, + }, + }, + { + # Verify that GYP macros and POSIX paths work correctly. + 'target_name': 'test_pdb_proddir', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3' + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'ProgramDatabaseFile': '<(PRODUCT_DIR)/name_proddir.pdb', + }, + }, + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/safeseh.gyp b/tools/gyp/test/win/linker-flags/safeseh.gyp new file mode 100644 index 00000000000000..d4a62074b8f94c --- /dev/null +++ b/tools/gyp/test/win/linker-flags/safeseh.gyp @@ -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 --git a/tools/gyp/test/win/linker-flags/safeseh_hello.cc b/tools/gyp/test/win/linker-flags/safeseh_hello.cc new file mode 100644 index 00000000000000..6141300d2c0a51 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/safeseh_hello.cc @@ -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 --git a/tools/gyp/test/win/linker-flags/safeseh_zero.asm b/tools/gyp/test/win/linker-flags/safeseh_zero.asm new file mode 100644 index 00000000000000..62da0df4f3359d --- /dev/null +++ b/tools/gyp/test/win/linker-flags/safeseh_zero.asm @@ -0,0 +1,10 @@ +.MODEL FLAT, C +.CODE + +PUBLIC zero +zero PROC + xor eax, eax + ret 0 +zero ENDP + +END diff --git a/tools/gyp/test/win/linker-flags/safeseh_zero64.asm b/tools/gyp/test/win/linker-flags/safeseh_zero64.asm new file mode 100644 index 00000000000000..a4740c0dfb5abd --- /dev/null +++ b/tools/gyp/test/win/linker-flags/safeseh_zero64.asm @@ -0,0 +1,9 @@ +.CODE + +PUBLIC zero +zero PROC + xor eax, eax + ret 0 +zero ENDP + +END diff --git a/tools/gyp/test/win/linker-flags/stacksize.gyp b/tools/gyp/test/win/linker-flags/stacksize.gyp new file mode 100644 index 00000000000000..bba44ca4a71dee --- /dev/null +++ b/tools/gyp/test/win/linker-flags/stacksize.gyp @@ -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 --git a/tools/gyp/test/win/linker-flags/subdir/library.gyp b/tools/gyp/test/win/linker-flags/subdir/library.gyp new file mode 100644 index 00000000000000..9b4bd1d63178e4 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/subdir/library.gyp @@ -0,0 +1,13 @@ +# 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_lib', + 'type': 'static_library', + 'sources': ['../library-directories-define.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/subsystem-windows.cc b/tools/gyp/test/win/linker-flags/subsystem-windows.cc new file mode 100644 index 00000000000000..ac99da808ebd7f --- /dev/null +++ b/tools/gyp/test/win/linker-flags/subsystem-windows.cc @@ -0,0 +1,9 @@ +// 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 CALLBACK WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { + return 0; +} diff --git a/tools/gyp/test/win/linker-flags/subsystem.gyp b/tools/gyp/test/win/linker-flags/subsystem.gyp new file mode 100644 index 00000000000000..63f072a2067628 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/subsystem.gyp @@ -0,0 +1,70 @@ +# 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_console_ok', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'SubSystem': '1' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_console_fail', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'SubSystem': '1' + } + }, + 'sources': ['subsystem-windows.cc'], + }, + { + 'target_name': 'test_windows_ok', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'SubSystem': '2' + } + }, + 'sources': ['subsystem-windows.cc'], + }, + { + 'target_name': 'test_windows_fail', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'SubSystem': '2' + } + }, + '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 --git a/tools/gyp/test/win/linker-flags/target-machine.gyp b/tools/gyp/test/win/linker-flags/target-machine.gyp new file mode 100644 index 00000000000000..30271926c9f226 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/target-machine.gyp @@ -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 --git a/tools/gyp/test/win/linker-flags/tsaware.gyp b/tools/gyp/test/win/linker-flags/tsaware.gyp new file mode 100644 index 00000000000000..7ffc7426bbfef8 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/tsaware.gyp @@ -0,0 +1,28 @@ +# 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_tsaware_no', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'TerminalServerAware': '1', + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_tsaware_yes', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'TerminalServerAware': '2', + }, + }, + 'sources': ['hello.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/linker-flags/unsupported-manifest.gyp b/tools/gyp/test/win/linker-flags/unsupported-manifest.gyp new file mode 100644 index 00000000000000..5549e7cb9bd6f8 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/unsupported-manifest.gyp @@ -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 --git a/tools/gyp/test/win/linker-flags/update_pgd.py b/tools/gyp/test/win/linker-flags/update_pgd.py new file mode 100644 index 00000000000000..176e9e5472f0cd --- /dev/null +++ b/tools/gyp/test/win/linker-flags/update_pgd.py @@ -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 --git a/tools/gyp/test/win/linker-flags/warn-as-error.gyp b/tools/gyp/test/win/linker-flags/warn-as-error.gyp new file mode 100644 index 00000000000000..600eb0c353fa09 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/warn-as-error.gyp @@ -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 --git a/tools/gyp/test/win/linker-flags/x.cc b/tools/gyp/test/win/linker-flags/x.cc new file mode 100644 index 00000000000000..f5f763b0956348 --- /dev/null +++ b/tools/gyp/test/win/linker-flags/x.cc @@ -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 --git a/tools/gyp/test/win/linker-flags/y.cc b/tools/gyp/test/win/linker-flags/y.cc new file mode 100644 index 00000000000000..bd884119fcd44a --- /dev/null +++ b/tools/gyp/test/win/linker-flags/y.cc @@ -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 --git a/tools/gyp/test/win/linker-flags/z.cc b/tools/gyp/test/win/linker-flags/z.cc new file mode 100644 index 00000000000000..8a43501270ae8a --- /dev/null +++ b/tools/gyp/test/win/linker-flags/z.cc @@ -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 --git a/tools/gyp/test/win/long-command-line/function.cc b/tools/gyp/test/win/long-command-line/function.cc new file mode 100644 index 00000000000000..af44b2cabd6bb8 --- /dev/null +++ b/tools/gyp/test/win/long-command-line/function.cc @@ -0,0 +1,7 @@ +// 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. + +int func() { + return 0; +} diff --git a/tools/gyp/test/win/long-command-line/hello.cc b/tools/gyp/test/win/long-command-line/hello.cc new file mode 100644 index 00000000000000..1711567ef56670 --- /dev/null +++ b/tools/gyp/test/win/long-command-line/hello.cc @@ -0,0 +1,7 @@ +// 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. + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/long-command-line/long-command-line.gyp b/tools/gyp/test/win/long-command-line/long-command-line.gyp new file mode 100644 index 00000000000000..7381a2051b65cd --- /dev/null +++ b/tools/gyp/test/win/long-command-line/long-command-line.gyp @@ -0,0 +1,54 @@ +# 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': 'longexe', + 'type': 'executable', + 'msvs_settings': { + # Use this as a simple way to get a long command. + 'VCCLCompilerTool': { + 'AdditionalOptions': '/nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo', + }, + 'VCLinkerTool': { + 'AdditionalOptions': '/nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo', + }, + }, + 'sources': [ + 'hello.cc', + ], + }, + { + 'target_name': 'longlib', + 'type': 'static_library', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'AdditionalOptions': '/nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo', + }, + 'VCLibrarianTool': { + 'AdditionalOptions': '/nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo', + }, + }, + 'sources': [ + 'function.cc', + ], + }, + { + 'target_name': 'longdll', + 'type': 'shared_library', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'AdditionalOptions': '/nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo', + }, + 'VCLinkerTool': { + 'AdditionalOptions': '/nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo /nologo', + }, + }, + 'sources': [ + 'hello.cc', + ], + }, + ] +} diff --git a/tools/gyp/test/win/ml-safeseh/a.asm b/tools/gyp/test/win/ml-safeseh/a.asm new file mode 100644 index 00000000000000..62da0df4f3359d --- /dev/null +++ b/tools/gyp/test/win/ml-safeseh/a.asm @@ -0,0 +1,10 @@ +.MODEL FLAT, C +.CODE + +PUBLIC zero +zero PROC + xor eax, eax + ret 0 +zero ENDP + +END diff --git a/tools/gyp/test/win/ml-safeseh/hello.cc b/tools/gyp/test/win/ml-safeseh/hello.cc new file mode 100644 index 00000000000000..6141300d2c0a51 --- /dev/null +++ b/tools/gyp/test/win/ml-safeseh/hello.cc @@ -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 --git a/tools/gyp/test/win/ml-safeseh/ml-safeseh.gyp b/tools/gyp/test/win/ml-safeseh/ml-safeseh.gyp new file mode 100644 index 00000000000000..bf8618f865623d --- /dev/null +++ b/tools/gyp/test/win/ml-safeseh/ml-safeseh.gyp @@ -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 --git a/tools/gyp/test/win/precompiled/gyptest-all.py b/tools/gyp/test/win/precompiled/gyptest-all.py new file mode 100644 index 00000000000000..9fb5e62edf464d --- /dev/null +++ b/tools/gyp/test/win/precompiled/gyptest-all.py @@ -0,0 +1,21 @@ +#!/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 precompiled headers can be specified. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja'], workdir='workarea_all') + test.run_gyp('hello.gyp') + test.build('hello.gyp', 'hello') + test.run_built_executable('hello', stdout="Hello, world!\nHello, two!\n") + test.up_to_date('hello.gyp', test.ALL) + test.pass_test() diff --git a/tools/gyp/test/win/precompiled/hello.c b/tools/gyp/test/win/precompiled/hello.c new file mode 100644 index 00000000000000..ffb47bf8221984 --- /dev/null +++ b/tools/gyp/test/win/precompiled/hello.c @@ -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. */ + +// Note the abscence of a stdio.h include. This will be inserted because of the +// precompiled header. + +extern int hello2(); + +int main(void) { + printf("Hello, world!\n"); + hello2(); + return 0; +} diff --git a/tools/gyp/test/win/precompiled/hello.gyp b/tools/gyp/test/win/precompiled/hello.gyp new file mode 100644 index 00000000000000..5f82c535939eac --- /dev/null +++ b/tools/gyp/test/win/precompiled/hello.gyp @@ -0,0 +1,28 @@ +# 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': [ + 'hello.c', + 'hello2.c', + 'precomp.c', + ], + 'msvs_precompiled_header': 'stdio.h', + 'msvs_precompiled_source': 'precomp.c', + + # Required so that the printf actually causes a build failure + # if the pch isn't included. + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarningLevel': '3', + 'WarnAsError': 'true', + }, + }, + }, + ], +} diff --git a/tools/gyp/test/win/precompiled/hello2.c b/tools/gyp/test/win/precompiled/hello2.c new file mode 100644 index 00000000000000..d6d53111fb80d5 --- /dev/null +++ b/tools/gyp/test/win/precompiled/hello2.c @@ -0,0 +1,13 @@ +/* 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. */ + +// Unlike hello.c, this file specifies the headers. + +#include +#include + +int hello2() { + printf("Hello, two!\n"); + return 0; +} diff --git a/tools/gyp/test/win/precompiled/precomp.c b/tools/gyp/test/win/precompiled/precomp.c new file mode 100644 index 00000000000000..517c61a36ba476 --- /dev/null +++ b/tools/gyp/test/win/precompiled/precomp.c @@ -0,0 +1,8 @@ +/* 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. */ + +// The precompiled header does not have to be the first one in the file. + +#include +#include diff --git a/tools/gyp/test/win/rc-build/Resource.h b/tools/gyp/test/win/rc-build/Resource.h new file mode 100644 index 00000000000000..2f50df91a75162 --- /dev/null +++ b/tools/gyp/test/win/rc-build/Resource.h @@ -0,0 +1,26 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by hello.rc +// + +#define IDS_APP_TITLE 103 + +#define IDR_MAINFRAME 128 +#define IDI_HELLO 107 +#define IDI_SMALL 108 +#define IDC_HELLO 109 +#ifndef IDC_STATIC +#define IDC_STATIC -1 +#endif +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NO_MFC 130 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/tools/gyp/test/win/rc-build/hello.cpp b/tools/gyp/test/win/rc-build/hello.cpp new file mode 100644 index 00000000000000..866078ee896d4e --- /dev/null +++ b/tools/gyp/test/win/rc-build/hello.cpp @@ -0,0 +1,30 @@ +// 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. + +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include "resource.h" + +#define MAX_LOADSTRING 100 + +TCHAR szTitle[MAX_LOADSTRING]; +TCHAR szWindowClass[MAX_LOADSTRING]; + +int APIENTRY _tWinMain( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, + int nCmdShow) { + // Make sure we can load some resources. + int count = 0; + LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); + if (szTitle[0] != 0) ++count; + LoadString(hInstance, IDC_HELLO, szWindowClass, MAX_LOADSTRING); + if (szWindowClass[0] != 0) ++count; + if (LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SMALL)) != NULL) ++count; + if (LoadIcon(hInstance, MAKEINTRESOURCE(IDI_HELLO)) != NULL) ++count; + return count; +} diff --git a/tools/gyp/test/win/rc-build/hello.gyp b/tools/gyp/test/win/rc-build/hello.gyp new file mode 100644 index 00000000000000..3a66357dd4a73a --- /dev/null +++ b/tools/gyp/test/win/rc-build/hello.gyp @@ -0,0 +1,92 @@ +# 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': 'with_resources', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + }, + 'VCResourceCompilerTool': { + 'Culture' : '1033', + }, + }, + 'sources': [ + 'hello.cpp', + 'hello.rc', + ], + 'libraries': [ + 'kernel32.lib', + 'user32.lib', + ], + }, + { + 'target_name': 'with_resources_subdir', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + }, + 'VCResourceCompilerTool': { + 'Culture' : '1033', + }, + }, + 'sources': [ + 'hello.cpp', + 'subdir/hello2.rc', + ], + 'libraries': [ + 'kernel32.lib', + 'user32.lib', + ], + }, + { + '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': { + 'VCLinkerTool': { + 'ResourceOnlyDLL': 'true', + }, + }, + 'sources': [ + 'hello.rc', + ], + }, + ], +} diff --git a/tools/gyp/test/win/rc-build/hello.h b/tools/gyp/test/win/rc-build/hello.h new file mode 100644 index 00000000000000..d00d47e7885087 --- /dev/null +++ b/tools/gyp/test/win/rc-build/hello.h @@ -0,0 +1,3 @@ +#pragma once + +#include "resource.h" diff --git a/tools/gyp/test/win/rc-build/hello.ico b/tools/gyp/test/win/rc-build/hello.ico new file mode 100644 index 0000000000000000000000000000000000000000..d551aa3aaf80adf9b7760e2eb8de95a5c3e53df6 GIT binary patch literal 23558 zcmeI430zgx+QuJHKtxbe5gbu*030B5$VyGcDGSFOalkY&2LuvC5pp(7&2XNl96=@z zNXGH2`|DO#nx)3nwUq43A>_N=+wHsYe$U#6ePmShD&p^B>2uySylbs@uYIPy&-w#c zpc-6UYC)x+ErDgUwQ8BlZ7hIURRB*7exZ#T}AXG2* z=^weGTI5~Inq#r?3QZRh5>Vvy7AqDy*^i;1p6BY7;LQSXZ{;g>M z?fm5AM!1uJ~14CP5-;mbWJGeF0 z_iurN!(6GBI54yo4h(CB{j~e(6Em$hj*V=Fqpvo{5$e#07L+U2`wvFkn8s8S#Efo= z^|!}o{tozLT1|Z7UlaSMxZ(5FgK^Rilm(Khv|vko7i5X}36?lI))Ggklas69 zVxSe$=33+10BfA^v%)uXY;b;dHGCaV4e6oPadwt1PEE7L#SjO4G`kKy33kG#^P1yK zcx(J^Ra<Ti+?95-JJvGIWK0JnTs;vs^DcXy)=jK$w z=lme~e0CM~SM61i7E+Zy6!Vv8(?YCpX|5H%3$bS21{dbq;8I96Tne>C8jm-9o*mM| z?2r~#1K&~U^BwT@ygK+I#1UDG8sIO%&iE*}A+E1$jbGNa!S(fRas9ovxba>)TBY{5 zxxo`Rq9|oIDtY0?rjE#1t!!u9+}s5>w|2#i&D55z%y+}h?JrQ>af9~O4zA^n9=Nr$ z7jEt9gPXg&@$23JxV49(y|Q~4emOiI-)H_6dH=qKoBYhlq5e+&PW_AegZf|U-_)N} z9@RJC3MS7vp?yXL1qC4>AOQaU{+Kjr5++WZhzS!Wz}MFoW5Wxo&I+1!G$zZHn#$;`!98-<yjHIyy#~ zd!^|5sm6LSF)_!K%8;V#rWzZU(N_%@(#Q5Ewg{KRHI95 zY?=LIo2D9@#Ky*zb^O>SmHu~IE44l?Dgh-;K81z)WLJ`;4wqn z_ZrZ%LmzL?wy3kD_lL%jZ@l`n*YIJJ=8o?=KVm^dc=tK8XTNSrUK1xwofb5!|4WPJ z4;&O=5uecStt8`&$o&U)@7lX>*XEsj-g|fBj_upFZrx%^n^vq{{r0M5OP8-%`Odni z4ek1_pUw~WS3(xf3w~KkBmDdVRSL~dfr0)bOf7sI@n%@?lm1=c0pd4Z&T02Hm@RH2 z)we;5{I7(S*0d0%twR;wLsA|##n-X4buN70s`TsBg@MbpxknH6!QPjfV-K~P+VA6v z_lLE?{$Xwi?eB?&gE}IlpC>|?5A<%2&;edpIl33d4IhkA?7Qcs#@NdnYWsbf({dao zjuAS*69M!eGt37G)4CyX#*2ub-V>ij1>vuo!mzs+z)KgL@b7{zHqOE48v-$!zJ3#Y zv6uJbc6$T6dQ*KU=65px!K_Y5n$a2Cr*_9zn`Ys&O+gqt+y{pT0q+l>1_JwOKM87w zj|1D|zXCjwI@=4Ewok|DRTFSw+Z#B)bq3CDnTav%mol33yacQq;D9qB?)YqOTV(8< zhO{02IO`82u>Hs|UYpK$#ksIn_%f8&v3sW=YtK}ip9y^Z1~r3H`B~I#;2iDQ=@jeE zsP;Kl_%^%|E=9QF`(^IPTIr6TH*`S`ui5^ww+}9?dJfr}dg8{OA;>xEhiiu?LYUzwb+T)8Ci=PAZtkjWKvm68X{|HBivlm3|Y&X;^sP6+GhB5eJk92w>5I2 z+$j(Ix}hC1827D>9dK(?2jp()h@8zG@!QT$$l2N%x3+e|?QJ|JOre?J8PhnJ%Ni~CLrzWB&44|iS%zyB8@if zn`DaR3m@|O^QyPhwX#dzrgIKY+OQIBHLeiIw|EP z&VT0+jvL~&)rdRJe}-vnAIJ6*Q-ZDH1N-*w-gRv2&ZLw99b3D3xO=#{xw*T!wQ+Oz@bGBcd0?|n&$#sN_2S8-lrFX#RqEa{~iIg60Iwp0)kazxeJo zgX#N&>G3k(9Zpk`k46?8yGp_NR9<~gx%0b2>EBc6h6N*s;*a0{2Wy6O#7ZA8q(u55 zXmAg#9`ZC+QBk9x#nSQpa4CKpR!sCp#>stnXRBl-)qQFW^fsryy=(Z?FI2AS<5;lV$HB*W zpm$$$hhFu3THa~z+qYL;AE$u>2QZl)2G;Ru)3f^vUAny3rOUHDp6~jct50i}CXE|6 zZPK7&qvp+?vT*b1+^M5y`wmZgdAPT0`%H^xiXL6DvWOu*60xx;u6V#Q2{0r8adCy( zEn;IuV&g28p4jI>W#CW53OF&!CsAr~RottogHM>&s@S>DKq|7h|3SD9 zqF9XiYwfgmNUJRFhY%(1o6xLY)@?;QKJMM%9Zv1};>0~2!r#}0zp0zW`xNH9UeDj( zg}=XRQtjm}{_d~Eq+;bB6m$ICmr^L!lH$^jp`^CQQOEr>=J>f^rrg)^KRssd^D)QI zeLuo|80KTp^Sb>{=X%)v)pLRSmCW&T|B@EJinpT1Tyzb%m&zPJ_g4w`z?hFg`Rd1_ z>Wj7&9jm;{DmLy1Gsn+8Vp@!PtSTNouWWh8cdz+W{M_4Sj-PwjDs;R>k4LR3_uiS~ z=YBll{weJklr8FC(aI`*?jJPA&pn00ytW2@1pNNmFr)z)}MRaMZIsT^P*Jr zd{v~ficiI=V%Fb3xlf-prc}}2|5bcSDrP-?@&@_Qn~c8Rs-)*Df-M*%`H0H+%lZ72 zvi{EGQOr#h;dxS84CWx2AwMJBn{b$~fyU%&3N}@!=X}9qDHtRuG5tUm68j-~fkG1sqOUyGmYlwPgb z2OYaS`ssnHnDzL{f$7y1HvU2ZvOsRl96y=1qRkb)O#V)fzZuy)A>;K#iJYK%{YIx)`7mahDM1B1t%cm9kaZNYkD4X_DC9qd+$8->B5TQhB} zPLpFP(T5^y$$V8IA1dTRh5V#84>?gGBg(O=3b|S#mnh^Cg)FI%vsB;THmdl^aSGW> zA@3;U9fcgEkcSj)tKX)y|CMyJ9 zWMGAisgNZVGNwZIRLI7bES?uKuA0cIN->306SAtME58p}SdPK5N}H!(y?QQ$SPR)# zEw=cH;9p8myVEOE~ZJrY}3iIg?0rP&%LTBp=}8h@I%TXv<9-xUO`%}-uWt5a*E=2Z6^)Nip$4?6}mrb=W3r9pMm{N(?%I<=0f{ZX!iK0oKQ1d^EdG#^%`N>O4Lp#&)lc_BC`N?cbBh&ou z$Ha>#mE4>Z3XbJ2L!+Nt++W%XmzCnEDKwe#1XEVN#&9kX7z*Ba>aDt~p(O7d58 ztNMbLMIj4qo}V1Gs?t)?V|bWl{j*<9L>}8bKN)V*HyMT)&Xn7jpKpqbGz6zmVk@{(S%;moMb= zg`B=PIy$QPUCF}>xq2agFXZoq+`W*w*DN`FAuBIr%G&-D!IW`F9}` zFJ#_@jJ%MQmz-@~sV+i3UdYL7B1xFE+kg*rC_sn}}eaYVo*?J*YFZ>$;!oOJ{ z{QCgB-)1FF4i?imzkPZz{4Rvr{h7I>sgUu{%LsSK%b0JUml0-1RnN;GSP!(-+jpO%JopO`B((dnpK-(&yRaUJ6F; zchnE_k$Wv1f4{oG;*T$8Vx5|ss!Wf01@yO_$nuNBLZ4Gvb)Vu6x9f7RD3t3{RPFna z@~=**zWfUs8kYPPZCSL4e)B1xT|TXnSM+U>y|{O?8%m4vtzIr_BVKg5vCP}`*3dR} z&a!{N#n>%>kU18z!$Q_q$meQ#RW3=oZ=knFmg=8&V&`qOUg~p1N&lWwnpHmPb9YW3 zw+z)kIP(xwOMAJX5{|A*v__uZdtvV;w2rOkgeCCc1i z#a5Q%Amc3IgIa3+fBIm(x&OWTs_~Un|HxNN{coH$#m{POUDev^Dy>e{FMhe1Y5iiu zZ_N=+wHsYe$U#6ePmShD&p^B>2uySylbs@uYIPy&-w#c zpc-6UYC)x+ErDgUwQ8BlZ7hIURRB*7exZ#T}AXG2* z=^weGTI5~Inq#r?3QZRh5>Vvy7AqDy*^i;1p6BY7;LQSXZ{;g>M z?fm5AM!1uJ~14CP5-;mbWJGeF0 z_iurN!(6GBI54yo4h(CB{j~e(6Em$hj*V=Fqpvo{5$e#07L+U2`wvFkn8s8S#Efo= z^|!}o{tozLT1|Z7UlaSMxZ(5FgK^Rilm(Khv|vko7i5X}36?lI))Ggklas69 zVxSe$=33+10BfA^v%)uXY;b;dHGCaV4e6oPadwt1PEE7L#SjO4G`kKy33kG#^P1yK zcx(J^Ra<Ti+?95-JJvGIWK0JnTs;vs^DcXy)=jK$w z=lme~e0CM~SM61i7E+Zy6!Vv8(?YCpX|5H%3$bS21{dbq;8I96Tne>C8jm-9o*mM| z?2r~#1K&~U^BwT@ygK+I#1UDG8sIO%&iE*}A+E1$jbGNa!S(fRas9ovxba>)TBY{5 zxxo`Rq9|oIDtY0?rjE#1t!!u9+}s5>w|2#i&D55z%y+}h?JrQ>af9~O4zA^n9=Nr$ z7jEt9gPXg&@$23JxV49(y|Q~4emOiI-)H_6dH=qKoBYhlq5e+&PW_AegZf|U-_)N} z9@RJC3MS7vp?yXL1qC4>AOQaU{+Kjr5++WZhzS!Wz}MFoW5Wxo&I+1!G$zZHn#$;`!98-<yjHIyy#~ zd!^|5sm6LSF)_!K%8;V#rWzZU(N_%@(#Q5Ewg{KRHI95 zY?=LIo2D9@#Ky*zb^O>SmHu~IE44l?Dgh-;K81z)WLJ`;4wqn z_ZrZ%LmzL?wy3kD_lL%jZ@l`n*YIJJ=8o?=KVm^dc=tK8XTNSrUK1xwofb5!|4WPJ z4;&O=5uecStt8`&$o&U)@7lX>*XEsj-g|fBj_upFZrx%^n^vq{{r0M5OP8-%`Odni z4ek1_pUw~WS3(xf3w~KkBmDdVRSL~dfr0)bOf7sI@n%@?lm1=c0pd4Z&T02Hm@RH2 z)we;5{I7(S*0d0%twR;wLsA|##n-X4buN70s`TsBg@MbpxknH6!QPjfV-K~P+VA6v z_lLE?{$Xwi?eB?&gE}IlpC>|?5A<%2&;edpIl33d4IhkA?7Qcs#@NdnYWsbf({dao zjuAS*69M!eGt37G)4CyX#*2ub-V>ij1>vuo!mzs+z)KgL@b7{zHqOE48v-$!zJ3#Y zv6uJbc6$T6dQ*KU=65px!K_Y5n$a2Cr*_9zn`Ys&O+gqt+y{pT0q+l>1_JwOKM87w zj|1D|zXCjwI@=4Ewok|DRTFSw+Z#B)bq3CDnTav%mol33yacQq;D9qB?)YqOTV(8< zhO{02IO`82u>Hs|UYpK$#ksIn_%f8&v3sW=YtK}ip9y^Z1~r3H`B~I#;2iDQ=@jeE zsP;Kl_%^%|E=9QF`(^IPTIr6TH*`S`ui5^ww+}9?dJfr}dg8{OA;>xEhiiu?LYUzwb+T)8Ci=PAZtkjWKvm68X{|HBivlm3|Y&X;^sP6+GhB5eJk92w>5I2 z+$j(Ix}hC1827D>9dK(?2jp()h@8zG@!QT$$l2N%x3+e|?QJ|JOre?J8PhnJ%Ni~CLrzWB&44|iS%zyB8@if zn`DaR3m@|O^QyPhwX#dzrgIKY+OQIBHLeiIw|EP z&VT0+jvL~&)rdRJe}-vnAIJ6*Q-ZDH1N-*w-gRv2&ZLw99b3D3xO=#{xw*T!wQ+Oz@bGBcd0?|n&$#sN_2S8-lrFX#RqEa{~iIg60Iwp0)kazxeJo zgX#N&>G3k(9Zpk`k46?8yGp_NR9<~gx%0b2>EBc6h6N*s;*a0{2Wy6O#7ZA8q(u55 zXmAg#9`ZC+QBk9x#nSQpa4CKpR!sCp#>stnXRBl-)qQFW^fsryy=(Z?FI2AS<5;lV$HB*W zpm$$$hhFu3THa~z+qYL;AE$u>2QZl)2G;Ru)3f^vUAny3rOUHDp6~jct50i}CXE|6 zZPK7&qvp+?vT*b1+^M5y`wmZgdAPT0`%H^xiXL6DvWOu*60xx;u6V#Q2{0r8adCy( zEn;IuV&g28p4jI>W#CW53OF&!CsAr~RottogHM>&s@S>DKq|7h|3SD9 zqF9XiYwfgmNUJRFhY%(1o6xLY)@?;QKJMM%9Zv1};>0~2!r#}0zp0zW`xNH9UeDj( zg}=XRQtjm}{_d~Eq+;bB6m$ICmr^L!lH$^jp`^CQQOEr>=J>f^rrg)^KRssd^D)QI zeLuo|80KTp^Sb>{=X%)v)pLRSmCW&T|B@EJinpT1Tyzb%m&zPJ_g4w`z?hFg`Rd1_ z>Wj7&9jm;{DmLy1Gsn+8Vp@!PtSTNouWWh8cdz+W{M_4Sj-PwjDs;R>k4LR3_uiS~ z=YBll{weJklr8FC(aI`*?jJPA&pn00ytW2@1pNNmFr)z)}MRaMZIsT^P*Jr zd{v~ficiI=V%Fb3xlf-prc}}2|5bcSDrP-?@&@_Qn~c8Rs-)*Df-M*%`H0H+%lZ72 zvi{EGQOr#h;dxS84CWx2AwMJBn{b$~fyU%&3N}@!=X}9qDHtRuG5tUm68j-~fkG1sqOUyGmYlwPgb z2OYaS`ssnHnDzL{f$7y1HvU2ZvOsRl96y=1qRkb)O#V)fzZuy)A>;K#iJYK%{YIx)`7mahDM1B1t%cm9kaZNYkD4X_DC9qd+$8->B5TQhB} zPLpFP(T5^y$$V8IA1dTRh5V#84>?gGBg(O=3b|S#mnh^Cg)FI%vsB;THmdl^aSGW> zA@3;U9fcgEkcSj)tKX)y|CMyJ9 zWMGAisgNZVGNwZIRLI7bES?uKuA0cIN->306SAtME58p}SdPK5N}H!(y?QQ$SPR)# zEw=cH;9p8myVEOE~ZJrY}3iIg?0rP&%LTBp=}8h@I%TXv<9-xUO`%}-uWt5a*E=2Z6^)Nip$4?6}mrb=W3r9pMm{N(?%I<=0f{ZX!iK0oKQ1d^EdG#^%`N>O4Lp#&)lc_BC`N?cbBh&ou z$Ha>#mE4>Z3XbJ2L!+Nt++W%XmzCnEDKwe#1XEVN#&9kX7z*Ba>aDt~p(O7d58 ztNMbLMIj4qo}V1Gs?t)?V|bWl{j*<9L>}8bKN)V*HyMT)&Xn7jpKpqbGz6zmVk@{(S%;moMb= zg`B=PIy$QPUCF}>xq2agFXZoq+`W*w*DN`FAuBIr%G&-D!IW`F9}` zFJ#_@jJ%MQmz-@~sV+i3UdYL7B1xFE+kg*rC_sn}}eaYVo*?J*YFZ>$;!oOJ{ z{QCgB-)1FF4i?imzkPZz{4Rvr{h7I>sgUu{%LsSK%b0JUml0-1RnN;GSP!(-+jpO%JopO`B((dnpK-(&yRaUJ6F; zchnE_k$Wv1f4{oG;*T$8Vx5|ss!Wf01@yO_$nuNBLZ4Gvb)Vu6x9f7RD3t3{RPFna z@~=**zWfUs8kYPPZCSL4e)B1xT|TXnSM+U>y|{O?8%m4vtzIr_BVKg5vCP}`*3dR} z&a!{N#n>%>kU18z!$Q_q$meQ#RW3=oZ=knFmg=8&V&`qOUg~p1N&lWwnpHmPb9YW3 zw+z)kIP(xwOMAJX5{|A*v__uZdtvV;w2rOkgeCCc1i z#a5Q%Amc3IgIa3+fBIm(x&OWTs_~Un|HxNN{coH$#m{POUDev^Dy>e{FMhe1Y5iiu zZ +#include + +int main() {} diff --git a/tools/gyp/test/win/system-include/test.gyp b/tools/gyp/test/win/system-include/test.gyp new file mode 100644 index 00000000000000..07f2636543b76c --- /dev/null +++ b/tools/gyp/test/win/system-include/test.gyp @@ -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 --git a/tools/gyp/test/win/uldi/a.cc b/tools/gyp/test/win/uldi/a.cc new file mode 100644 index 00000000000000..0fe05d5afb095b --- /dev/null +++ b/tools/gyp/test/win/uldi/a.cc @@ -0,0 +1,7 @@ +// 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. + +int some_function() { + return 0; +} diff --git a/tools/gyp/test/win/uldi/b.cc b/tools/gyp/test/win/uldi/b.cc new file mode 100644 index 00000000000000..0fe05d5afb095b --- /dev/null +++ b/tools/gyp/test/win/uldi/b.cc @@ -0,0 +1,7 @@ +// 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. + +int some_function() { + return 0; +} diff --git a/tools/gyp/test/win/uldi/dll.cc b/tools/gyp/test/win/uldi/dll.cc new file mode 100644 index 00000000000000..93a6c190033ee5 --- /dev/null +++ b/tools/gyp/test/win/uldi/dll.cc @@ -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. + +__declspec(dllexport) void SomeFunction() { +} diff --git a/tools/gyp/test/win/uldi/exe.cc b/tools/gyp/test/win/uldi/exe.cc new file mode 100644 index 00000000000000..b3039ace96f3ce --- /dev/null +++ b/tools/gyp/test/win/uldi/exe.cc @@ -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 --git a/tools/gyp/test/win/uldi/main.cc b/tools/gyp/test/win/uldi/main.cc new file mode 100644 index 00000000000000..81b46d863ab59d --- /dev/null +++ b/tools/gyp/test/win/uldi/main.cc @@ -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. + +extern int some_function(); + +int main() { + some_function(); + return 0; +} diff --git a/tools/gyp/test/win/uldi/uldi-depending-on-module.gyp b/tools/gyp/test/win/uldi/uldi-depending-on-module.gyp new file mode 100644 index 00000000000000..3e34de8418e48a --- /dev/null +++ b/tools/gyp/test/win/uldi/uldi-depending-on-module.gyp @@ -0,0 +1,42 @@ +# 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': 'an_exe', + 'type': 'executable', + 'sources': ['exe.cc'], + 'dependencies': [ + 'a_dll', + ], + }, + { + 'target_name': 'a_dll', + 'type': 'shared_library', + 'sources': ['dll.cc'], + 'dependencies': [ + 'a_lib', + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'UseLibraryDependencyInputs': 'true' + }, + }, + }, + { + 'target_name': 'a_lib', + 'type': 'static_library', + 'dependencies': [ + 'a_module', + ], + 'sources': ['a.cc'], + }, + { + 'target_name': 'a_module', + 'type': 'loadable_module', + 'sources': ['a.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/uldi/uldi.gyp b/tools/gyp/test/win/uldi/uldi.gyp new file mode 100644 index 00000000000000..c32f5e0956e41c --- /dev/null +++ b/tools/gyp/test/win/uldi/uldi.gyp @@ -0,0 +1,45 @@ +# 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': 'lib1', + 'type': 'static_library', + 'sources': ['a.cc'], + }, + { + 'target_name': 'final_uldi', + 'type': 'executable', + 'dependencies': [ + 'lib1', + 'lib2', + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'UseLibraryDependencyInputs': 'true' + }, + }, + 'sources': ['main.cc'], + }, + { + 'target_name': 'final_no_uldi', + 'type': 'executable', + 'dependencies': [ + 'lib1', + 'lib2', + ], + 'sources': ['main.cc'], + }, + { + 'target_name': 'lib2', + 'type': 'static_library', + # b.cc has the same named function as a.cc, but don't use the same name + # so that the .obj will have a different name. If the obj file has the + # same name, the linker will discard the obj file, invalidating the + # test. + 'sources': ['b.cc'], + }, + ] +} diff --git a/tools/gyp/test/win/vs-macros/as.py b/tools/gyp/test/win/vs-macros/as.py new file mode 100644 index 00000000000000..806c91d926cb1c --- /dev/null +++ b/tools/gyp/test/win/vs-macros/as.py @@ -0,0 +1,20 @@ +#!/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. + +from __future__ import print_function + +from optparse import OptionParser + +parser = OptionParser() +parser.add_option('-a', dest='platform') +parser.add_option('-o', dest='output') +parser.add_option('-p', dest='path') +(options, args) = parser.parse_args() + +f = open(options.output, 'w') +print('options', options, file=f) +print('args', args, file=f) +f.close() diff --git a/tools/gyp/test/win/vs-macros/containing-gyp.gyp b/tools/gyp/test/win/vs-macros/containing-gyp.gyp new file mode 100644 index 00000000000000..c07b639ff1c052 --- /dev/null +++ b/tools/gyp/test/win/vs-macros/containing-gyp.gyp @@ -0,0 +1,39 @@ +# 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_expansions', + 'msvs_cygwin_shell': 0, + 'type': 'none', + 'rules': [ + { + 'rule_name': 'assembler (gnu-compatible)', + 'msvs_cygwin_shell': 0, + 'msvs_quote_cmd': 0, + 'extension': 'S', + 'inputs': [ + 'as.py', + ], + 'outputs': [ + '$(IntDir)/$(InputName).obj', + ], + 'action': + ['python', + 'as.py', + '-a', '$(PlatformName)', + '-o', '$(IntDir)/$(InputName).obj', + '-p', '<(DEPTH)', + '$(InputPath)'], + 'message': 'Building assembly language file $(InputPath)', + 'process_outputs_as_sources': 1, + }, + ], + 'sources': [ + 'input.S', + ], + }, + ] +} diff --git a/tools/gyp/test/win/vs-macros/do_stuff.py b/tools/gyp/test/win/vs-macros/do_stuff.py new file mode 100644 index 00000000000000..4669d3139b8cec --- /dev/null +++ b/tools/gyp/test/win/vs-macros/do_stuff.py @@ -0,0 +1,8 @@ +# 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. + +import sys + +input = open(sys.argv[1], "r").read() +open(sys.argv[2], "w").write(input + "Modified.") diff --git a/tools/gyp/test/win/vs-macros/hello.cc b/tools/gyp/test/win/vs-macros/hello.cc new file mode 100644 index 00000000000000..1711567ef56670 --- /dev/null +++ b/tools/gyp/test/win/vs-macros/hello.cc @@ -0,0 +1,7 @@ +// 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. + +int main() { + return 0; +} diff --git a/tools/gyp/test/win/vs-macros/input-output-macros.gyp b/tools/gyp/test/win/vs-macros/input-output-macros.gyp new file mode 100644 index 00000000000000..b4520f8cb8d337 --- /dev/null +++ b/tools/gyp/test/win/vs-macros/input-output-macros.gyp @@ -0,0 +1,32 @@ +# 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_expansions', + 'msvs_cygwin_shell': 0, + 'type': 'none', + 'rules': [ + { + 'rule_name': 'generate_file', + 'extension': 'blah', + 'inputs': [ + 'do_stuff.py', + ], + 'outputs': [ + '$(OutDir)\\<(RULE_INPUT_NAME).something', + ], + 'action': ['python', + 'do_stuff.py', + '<(RULE_INPUT_PATH)', + '$(OutDir)\\<(RULE_INPUT_NAME).something',], + }, + ], + 'sources': [ + 'stuff.blah', + ], + }, + ] +} diff --git a/tools/gyp/test/win/vs-macros/input.S b/tools/gyp/test/win/vs-macros/input.S new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/test/win/vs-macros/projectname.gyp b/tools/gyp/test/win/vs-macros/projectname.gyp new file mode 100644 index 00000000000000..625a1776435738 --- /dev/null +++ b/tools/gyp/test/win/vs-macros/projectname.gyp @@ -0,0 +1,29 @@ +# 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_expansions', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(OutDir)\\$(ProjectName)_plus_something.exe', + }, + }, + }, + { + 'target_name': 'test_with_product_name', + 'product_name': 'prod_name', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(OutDir)\\$(ProjectName)_plus_something.exe', + }, + }, + }, + ] +} diff --git a/tools/gyp/test/win/vs-macros/stuff.blah b/tools/gyp/test/win/vs-macros/stuff.blah new file mode 100644 index 00000000000000..d438b4a787c5dd --- /dev/null +++ b/tools/gyp/test/win/vs-macros/stuff.blah @@ -0,0 +1 @@ +Random data file. diff --git a/tools/gyp/test/win/vs-macros/targetext.gyp b/tools/gyp/test/win/vs-macros/targetext.gyp new file mode 100644 index 00000000000000..11f580e4a602a3 --- /dev/null +++ b/tools/gyp/test/win/vs-macros/targetext.gyp @@ -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 --git a/tools/gyp/test/win/vs-macros/targetfilename.gyp b/tools/gyp/test/win/vs-macros/targetfilename.gyp new file mode 100644 index 00000000000000..82873202789ffe --- /dev/null +++ b/tools/gyp/test/win/vs-macros/targetfilename.gyp @@ -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 --git a/tools/gyp/test/win/vs-macros/targetname.gyp b/tools/gyp/test/win/vs-macros/targetname.gyp new file mode 100644 index 00000000000000..a53d3c0aa3bc63 --- /dev/null +++ b/tools/gyp/test/win/vs-macros/targetname.gyp @@ -0,0 +1,52 @@ +# 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_targetname', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(TargetDir)\\$(TargetName)_plus_something1.exe', + }, + }, + }, + { + 'target_name': 'test_targetname_with_prefix', + 'product_prefix': 'prod_prefix', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(TargetDir)\\$(TargetName)_plus_something2.exe', + }, + }, + }, + { + 'target_name': 'test_targetname_with_prodname', + 'product_name': 'prod_name', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(TargetDir)\\$(TargetName)_plus_something3.exe', + }, + }, + }, + { + 'target_name': 'test_targetname_with_prodname_with_prefix', + 'product_name': 'prod_name', + 'product_prefix': 'prod_prefix', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(TargetDir)\\$(TargetName)_plus_something4.exe', + }, + }, + }, + ] +} diff --git a/tools/gyp/test/win/vs-macros/targetpath.gyp b/tools/gyp/test/win/vs-macros/targetpath.gyp new file mode 100644 index 00000000000000..a8699ffb253419 --- /dev/null +++ b/tools/gyp/test/win/vs-macros/targetpath.gyp @@ -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 --git a/tools/gyp/test/win/vs-macros/test_exists.py b/tools/gyp/test/win/vs-macros/test_exists.py new file mode 100644 index 00000000000000..297b1b7d9f0a6e --- /dev/null +++ b/tools/gyp/test/win/vs-macros/test_exists.py @@ -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. + +import os +import sys + +if not os.path.exists(sys.argv[1]): + raise Exception() +open(sys.argv[2], 'w').close() diff --git a/tools/gyp/test/win/vs-macros/vcinstalldir.gyp b/tools/gyp/test/win/vs-macros/vcinstalldir.gyp new file mode 100644 index 00000000000000..3763a4eb182ea2 --- /dev/null +++ b/tools/gyp/test/win/vs-macros/vcinstalldir.gyp @@ -0,0 +1,41 @@ +# 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_slash_trailing', + 'type': 'none', + 'msvs_cygwin_shell': '0', + 'actions': [ + { + 'action_name': 'root', + 'inputs': [], + 'outputs': ['out1'], + 'action': ['python', 'test_exists.py', '$(VCInstallDir)', 'out1'] + }, + ], + }, + { + 'target_name': 'test_slash_dir', + 'type': 'none', + 'msvs_cygwin_shell': '0', + 'actions': [ + { + 'action_name': 'bin', + 'inputs': [], + 'outputs': ['out2'], + 'action': ['python', 'test_exists.py', '$(VCInstallDir)bin', 'out2'], + }, + { + 'action_name': 'compiler', + 'inputs': [], + 'outputs': ['out3'], + 'action': [ + 'python', 'test_exists.py', '$(VCInstallDir)bin\\cl.exe', 'out3'], + }, + ], + }, + ] +} diff --git a/tools/gyp/test/win/win-driver-target-type/win-driver-target-type.c b/tools/gyp/test/win/win-driver-target-type/win-driver-target-type.c new file mode 100644 index 00000000000000..a6bee029abd196 --- /dev/null +++ b/tools/gyp/test/win/win-driver-target-type/win-driver-target-type.c @@ -0,0 +1,10 @@ +// Copyright (c) 2016 Google 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 "win-driver-target-type.h" + +NTSTATUS DriverEntry(_In_ struct _DRIVER_OBJECT *DriverObject, + _In_ PUNICODE_STRING RegistryPath) { + return STATUS_SUCCESS; +} diff --git a/tools/gyp/test/win/win-driver-target-type/win-driver-target-type.gyp b/tools/gyp/test/win/win-driver-target-type/win-driver-target-type.gyp new file mode 100644 index 00000000000000..5da9cc9bd8bf7c --- /dev/null +++ b/tools/gyp/test/win/win-driver-target-type/win-driver-target-type.gyp @@ -0,0 +1,32 @@ +# Copyright (c) 2016 Google 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': 'win_driver_target_type', + 'type': 'windows_driver', + 'msvs_target_version': 'Windows7', + 'sources': [ + 'win-driver-target-type.c', + 'win-driver-target-type.h', + 'win-driver-target-type.rc', + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'AdditionalDependencies': [ + 'wdmsec.lib', + 'ntoskrnl.lib', + 'hal.lib', + 'wmilib.lib', + 'bufferoverflowfastfailk.lib', + ], + }, + 'VCCLCompilerTool': { + 'WarnAsError': 'false', + }, + }, + }, + ] +} diff --git a/tools/gyp/test/win/win-driver-target-type/win-driver-target-type.h b/tools/gyp/test/win/win-driver-target-type/win-driver-target-type.h new file mode 100644 index 00000000000000..5bbffd2373ee88 --- /dev/null +++ b/tools/gyp/test/win/win-driver-target-type/win-driver-target-type.h @@ -0,0 +1,13 @@ +// Copyright (c) 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE + +#ifndef _WIN_DRIVER_TARGET_TYPE_H_ +#define _WIN_DRIVER_TARGET_TYPE_H_ + +#include +#include + +DRIVER_INITIALIZE DriverEntry; + +#endif diff --git a/tools/gyp/test/win/win-driver-target-type/win-driver-target-type.rc b/tools/gyp/test/win/win-driver-target-type/win-driver-target-type.rc new file mode 100644 index 00000000000000..7a037ef7360253 --- /dev/null +++ b/tools/gyp/test/win/win-driver-target-type/win-driver-target-type.rc @@ -0,0 +1,14 @@ +// Copyright (c) 2016 Google 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 + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "Windows Driver GYP target type" +#define VER_INTERNALNAME_STR "win-driver-target-type.sys" +#define VER_ORIGINALFILENAME_STR "win-driver-target-type.sys" + +#include "common.ver" diff --git a/tools/gyp/test/win/win-tool/copies_readonly_files.gyp b/tools/gyp/test/win/win-tool/copies_readonly_files.gyp new file mode 100644 index 00000000000000..3cd7e69f1a2af7 --- /dev/null +++ b/tools/gyp/test/win/win-tool/copies_readonly_files.gyp @@ -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 --git a/tools/gyp/test/win/win-tool/gyptest-win-tool-handles-readonly-files.py b/tools/gyp/test/win/win-tool/gyptest-win-tool-handles-readonly-files.py new file mode 100644 index 00000000000000..951b9527756409 --- /dev/null +++ b/tools/gyp/test/win/win-tool/gyptest-win-tool-handles-readonly-files.py @@ -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 --git a/tools/gyp/test/win/winrt-app-type-revision/dllmain.cc b/tools/gyp/test/win/winrt-app-type-revision/dllmain.cc new file mode 100644 index 00000000000000..dedd83c3f66d60 --- /dev/null +++ b/tools/gyp/test/win/winrt-app-type-revision/dllmain.cc @@ -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 --git a/tools/gyp/test/win/winrt-app-type-revision/winrt-app-type-revision.gyp b/tools/gyp/test/win/winrt-app-type-revision/winrt-app-type-revision.gyp new file mode 100644 index 00000000000000..0c5daaaddea8e5 --- /dev/null +++ b/tools/gyp/test/win/winrt-app-type-revision/winrt-app-type-revision.gyp @@ -0,0 +1,35 @@ +# 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', + ], + }, + ] +} diff --git a/tools/gyp/test/win/winrt-target-platform-version/dllmain.cc b/tools/gyp/test/win/winrt-target-platform-version/dllmain.cc new file mode 100644 index 00000000000000..d71460c924d7b3 --- /dev/null +++ b/tools/gyp/test/win/winrt-target-platform-version/dllmain.cc @@ -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 --git a/tools/gyp/test/win/winrt-target-platform-version/winrt-target-platform-version.gyp b/tools/gyp/test/win/winrt-target-platform-version/winrt-target-platform-version.gyp new file mode 100644 index 00000000000000..ce4054fdbc2181 --- /dev/null +++ b/tools/gyp/test/win/winrt-target-platform-version/winrt-target-platform-version.gyp @@ -0,0 +1,45 @@ +{ + '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 --git a/tools/gyp/test/xcode-ninja/list_excluded/gyptest-all.py b/tools/gyp/test/xcode-ninja/list_excluded/gyptest-all.py new file mode 100644 index 00000000000000..2d6378a7a2fa79 --- /dev/null +++ b/tools/gyp/test/xcode-ninja/list_excluded/gyptest-all.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +# Copyright (c) 2016 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. + +""" +Verifies that excluded files are listed in sources_for_indexing.xcodeproj by +default, and that the generator flag xcode_ninja_list_excluded_files can be +used to override the default behavior. +""" + +import os +import TestGyp + + +test = TestGyp.TestGyp() + +if test.format != 'xcode-ninja': + test.skip_test() + + +# With the generator flag not set. +test.run_gyp('hello_exclude.gyp') +test.must_contain( + 'sources_for_indexing.xcodeproj/project.pbxproj', 'hello_excluded.cpp') + + +# With the generator flag set to 0. +try: + os.environ['GYP_GENERATOR_FLAGS'] = 'xcode_ninja_list_excluded_files=0' + test.run_gyp('hello_exclude.gyp') +finally: + del os.environ['GYP_GENERATOR_FLAGS'] +test.must_not_contain( + 'sources_for_indexing.xcodeproj/project.pbxproj', 'hello_excluded.cpp') + + +# With the generator flag explicitly set to 1. +try: + os.environ['GYP_GENERATOR_FLAGS'] = 'xcode_ninja_list_excluded_files=1' + test.run_gyp('hello_exclude.gyp') +finally: + del os.environ['GYP_GENERATOR_FLAGS'] +test.must_contain( + 'sources_for_indexing.xcodeproj/project.pbxproj', 'hello_excluded.cpp') + + +test.pass_test() diff --git a/tools/gyp/test/xcode-ninja/list_excluded/hello.cpp b/tools/gyp/test/xcode-ninja/list_excluded/hello.cpp new file mode 100644 index 00000000000000..cd409dabf9212a --- /dev/null +++ b/tools/gyp/test/xcode-ninja/list_excluded/hello.cpp @@ -0,0 +1,7 @@ +// Copyright (c) 2016 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. + +int main() { + return 0; +} diff --git a/tools/gyp/test/xcode-ninja/list_excluded/hello_exclude.gyp b/tools/gyp/test/xcode-ninja/list_excluded/hello_exclude.gyp new file mode 100644 index 00000000000000..f5f0e8eafdcba5 --- /dev/null +++ b/tools/gyp/test/xcode-ninja/list_excluded/hello_exclude.gyp @@ -0,0 +1,19 @@ +# Copyright (c) 2016 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': 'hello', + 'type': 'executable', + 'sources': [ + 'hello.cpp', + 'hello_excluded.cpp', + ], + 'sources!': [ + 'hello_excluded.cpp', + ], + }, + ], +} diff --git a/tools/gyp/test/xcode-ninja/list_excluded/hello_excluded.cpp b/tools/gyp/test/xcode-ninja/list_excluded/hello_excluded.cpp new file mode 100644 index 00000000000000..21155295423814 --- /dev/null +++ b/tools/gyp/test/xcode-ninja/list_excluded/hello_excluded.cpp @@ -0,0 +1,7 @@ +// Copyright (c) 2016 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. + +int main() { + return 42; +} diff --git a/tools/gyp/testlib/README.txt b/tools/gyp/testlib/README.txt new file mode 100644 index 00000000000000..813cc6eef34604 --- /dev/null +++ b/tools/gyp/testlib/README.txt @@ -0,0 +1,16 @@ +Supporting modules for GYP testing. + + SConsLib/ + + Modules for generic testing of command-line utilities, + specifically including the ability to copy a test configuration + to temporary directories (with default cleanup on exit) as part + of running test scripts that invoke commands, compare actual + against expected output, etc. + + Our copies of these come from the SCons project: + https://github.com/SCons/scons/tree/887f4a1b06ceed33ee6ba4c5589a32a607d6b001/testing/framework + + TestGyp.py + + Modules for GYP-specific tests, of course ;) diff --git a/tools/gyp/testlib/SConsLib/TestCmd.py b/tools/gyp/testlib/SConsLib/TestCmd.py new file mode 100644 index 00000000000000..d03f32af4ba20f --- /dev/null +++ b/tools/gyp/testlib/SConsLib/TestCmd.py @@ -0,0 +1,1929 @@ +""" +TestCmd.py: a testing framework for commands and scripts. + +The TestCmd module provides a framework for portable automated testing +of executable commands and scripts (in any language, not just Python), +especially commands and scripts that require file system interaction. + +In addition to running tests and evaluating conditions, the TestCmd +module manages and cleans up one or more temporary workspace +directories, and provides methods for creating files and directories in +those workspace directories from in-line data, here-documents), allowing +tests to be completely self-contained. + +A TestCmd environment object is created via the usual invocation: + + import TestCmd + test = TestCmd.TestCmd() + +There are a bunch of keyword arguments available at instantiation: + + test = TestCmd.TestCmd(description = 'string', + program = 'program_or_script_to_test', + interpreter = 'script_interpreter', + workdir = 'prefix', + subdir = 'subdir', + verbose = Boolean, + match = default_match_function, + match_stdout = default_match_stdout_function, + match_stderr = default_match_stderr_function, + diff = default_diff_stderr_function, + diff_stdout = default_diff_stdout_function, + diff_stderr = default_diff_stderr_function, + combine = Boolean) + +There are a bunch of methods that let you do different things: + + test.verbose_set(1) + + test.description_set('string') + + test.program_set('program_or_script_to_test') + + test.interpreter_set('script_interpreter') + test.interpreter_set(['script_interpreter', 'arg']) + + test.workdir_set('prefix') + test.workdir_set('') + + test.workpath('file') + test.workpath('subdir', 'file') + + test.subdir('subdir', ...) + + test.rmdir('subdir', ...) + + test.write('file', "contents\n") + test.write(['subdir', 'file'], "contents\n") + + test.read('file') + test.read(['subdir', 'file']) + test.read('file', mode) + test.read(['subdir', 'file'], mode) + + test.writable('dir', 1) + test.writable('dir', None) + + test.preserve(condition, ...) + + test.cleanup(condition) + + test.command_args(program = 'program_or_script_to_run', + interpreter = 'script_interpreter', + arguments = 'arguments to pass to program') + + test.run(program = 'program_or_script_to_run', + interpreter = 'script_interpreter', + arguments = 'arguments to pass to program', + chdir = 'directory_to_chdir_to', + stdin = 'input to feed to the program\n') + universal_newlines = True) + + p = test.start(program = 'program_or_script_to_run', + interpreter = 'script_interpreter', + arguments = 'arguments to pass to program', + universal_newlines = None) + + test.finish(self, p) + + test.pass_test() + test.pass_test(condition) + test.pass_test(condition, function) + + test.fail_test() + test.fail_test(condition) + test.fail_test(condition, function) + test.fail_test(condition, function, skip) + test.fail_test(condition, function, skip, message) + + test.no_result() + test.no_result(condition) + test.no_result(condition, function) + test.no_result(condition, function, skip) + + test.stdout() + test.stdout(run) + + test.stderr() + test.stderr(run) + + test.symlink(target, link) + + test.banner(string) + test.banner(string, width) + + test.diff(actual, expected) + + test.diff_stderr(actual, expected) + + test.diff_stdout(actual, expected) + + test.match(actual, expected) + + test.match_stderr(actual, expected) + + test.match_stdout(actual, expected) + + test.set_match_function(match, stdout, stderr) + + test.match_exact("actual 1\nactual 2\n", "expected 1\nexpected 2\n") + test.match_exact(["actual 1\n", "actual 2\n"], + ["expected 1\n", "expected 2\n"]) + test.match_caseinsensitive("Actual 1\nACTUAL 2\n", "expected 1\nEXPECTED 2\n") + + test.match_re("actual 1\nactual 2\n", regex_string) + test.match_re(["actual 1\n", "actual 2\n"], list_of_regexes) + + test.match_re_dotall("actual 1\nactual 2\n", regex_string) + test.match_re_dotall(["actual 1\n", "actual 2\n"], list_of_regexes) + + test.tempdir() + test.tempdir('temporary-directory') + + test.sleep() + test.sleep(seconds) + + test.where_is('foo') + test.where_is('foo', 'PATH1:PATH2') + test.where_is('foo', 'PATH1;PATH2', '.suffix3;.suffix4') + + test.unlink('file') + test.unlink('subdir', 'file') + +The TestCmd module provides pass_test(), fail_test(), and no_result() +unbound functions that report test results for use with the Aegis change +management system. These methods terminate the test immediately, +reporting PASSED, FAILED, or NO RESULT respectively, and exiting with +status 0 (success), 1 or 2 respectively. This allows for a distinction +between an actual failed test and a test that could not be properly +evaluated because of an external condition (such as a full file system +or incorrect permissions). + + import TestCmd + + TestCmd.pass_test() + TestCmd.pass_test(condition) + TestCmd.pass_test(condition, function) + + TestCmd.fail_test() + TestCmd.fail_test(condition) + TestCmd.fail_test(condition, function) + TestCmd.fail_test(condition, function, skip) + TestCmd.fail_test(condition, function, skip, message) + + TestCmd.no_result() + TestCmd.no_result(condition) + TestCmd.no_result(condition, function) + TestCmd.no_result(condition, function, skip) + +The TestCmd module also provides unbound global functions that handle +matching in the same way as the match_*() methods described above. + + import TestCmd + + test = TestCmd.TestCmd(match = TestCmd.match_exact) + + test = TestCmd.TestCmd(match = TestCmd.match_caseinsensitive) + + test = TestCmd.TestCmd(match = TestCmd.match_re) + + test = TestCmd.TestCmd(match = TestCmd.match_re_dotall) + +These functions are also available as static methods: + + import TestCmd + + test = TestCmd.TestCmd(match = TestCmd.TestCmd.match_exact) + + test = TestCmd.TestCmd(match = TestCmd.TestCmd.match_caseinsensitive) + + test = TestCmd.TestCmd(match = TestCmd.TestCmd.match_re) + + test = TestCmd.TestCmd(match = TestCmd.TestCmd.match_re_dotall) + +These static methods can be accessed by a string naming the method: + + import TestCmd + + test = TestCmd.TestCmd(match = 'match_exact') + + test = TestCmd.TestCmd(match = 'match_caseinsensitive') + + test = TestCmd.TestCmd(match = 'match_re') + + test = TestCmd.TestCmd(match = 'match_re_dotall') + +The TestCmd module provides unbound global functions that can be used +for the "diff" argument to TestCmd.TestCmd instantiation: + + import TestCmd + + test = TestCmd.TestCmd(match = TestCmd.match_re, + diff = TestCmd.diff_re) + + test = TestCmd.TestCmd(diff = TestCmd.simple_diff) + + test = TestCmd.TestCmd(diff = TestCmd.context_diff) + + test = TestCmd.TestCmd(diff = TestCmd.unified_diff) + +These functions are also available as static methods: + + import TestCmd + + test = TestCmd.TestCmd(match = TestCmd.TestCmd.match_re, + diff = TestCmd.TestCmd.diff_re) + + test = TestCmd.TestCmd(diff = TestCmd.TestCmd.simple_diff) + + test = TestCmd.TestCmd(diff = TestCmd.TestCmd.context_diff) + + test = TestCmd.TestCmd(diff = TestCmd.TestCmd.unified_diff) + +These static methods can be accessed by a string naming the method: + + import TestCmd + + test = TestCmd.TestCmd(match = 'match_re', diff = 'diff_re') + + test = TestCmd.TestCmd(diff = 'simple_diff') + + test = TestCmd.TestCmd(diff = 'context_diff') + + test = TestCmd.TestCmd(diff = 'unified_diff') + +The "diff" argument can also be used with standard difflib functions: + + import difflib + + test = TestCmd.TestCmd(diff = difflib.context_diff) + + test = TestCmd.TestCmd(diff = difflib.unified_diff) + +Lastly, the where_is() method also exists in an unbound function +version. + + import TestCmd + + TestCmd.where_is('foo') + TestCmd.where_is('foo', 'PATH1:PATH2') + TestCmd.where_is('foo', 'PATH1;PATH2', '.suffix3;.suffix4') +""" + +# Copyright 2000-2010 Steven Knight +# This module is free software, and you may redistribute it and/or modify +# it under the same terms as Python itself, so long as this copyright message +# and disclaimer are retained in their original form. +# +# IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +# SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF +# THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. +# +# THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, +# AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, +# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +from __future__ import division, print_function + +__author__ = "Steven Knight " +__revision__ = "TestCmd.py 1.3.D001 2010/06/03 12:58:27 knight" +__version__ = "1.3" + +import atexit +import difflib +import errno +import os +import re +import shutil +import signal +import stat +import sys +import tempfile +import threading +import time +import traceback +import types + + +IS_PY3 = sys.version_info[0] == 3 +IS_WINDOWS = sys.platform == 'win32' +IS_64_BIT = sys.maxsize > 2**32 + +class null(object): + pass + + +_Null = null() + +try: + from collections import UserList, UserString +except ImportError: + # no 'collections' module or no UserFoo in collections + exec('from UserList import UserList') + exec('from UserString import UserString') + +__all__ = [ + 'diff_re', + 'fail_test', + 'no_result', + 'pass_test', + 'match_exact', + 'match_caseinsensitive', + 'match_re', + 'match_re_dotall', + 'python', + '_python_', + 'TestCmd', + 'to_bytes', + 'to_str', +] + + +def is_List(e): + return isinstance(e, (list, UserList)) + + +def to_bytes(s): + if isinstance(s, bytes) or bytes is str: + return s + return bytes(s, 'utf-8') + + +def to_str(s): + if bytes is str or is_String(s): + return s + return str(s, 'utf-8') + + +try: + eval('unicode') +except NameError: + def is_String(e): + return isinstance(e, (str, UserString)) +else: + def is_String(e): + return isinstance(e, (str, unicode, UserString)) + +tempfile.template = 'testcmd.' +if os.name in ('posix', 'nt'): + tempfile.template = 'testcmd.' + str(os.getpid()) + '.' +else: + tempfile.template = 'testcmd.' + +re_space = re.compile('\s') + + +def _caller(tblist, skip): + string = "" + arr = [] + for file, line, name, text in tblist: + if file[-10:] == "TestCmd.py": + break + arr = [(file, line, name, text)] + arr + atfrom = "at" + for file, line, name, text in arr[skip:]: + if name in ("?", ""): + name = "" + else: + name = " (" + name + ")" + string = string + ("%s line %d of %s%s\n" % (atfrom, line, file, name)) + atfrom = "\tfrom" + return string + + +def fail_test(self=None, condition=1, function=None, skip=0, message=None): + """Cause the test to fail. + + By default, the fail_test() method reports that the test FAILED + and exits with a status of 1. If a condition argument is supplied, + the test fails only if the condition is true. + """ + if not condition: + return + if not function is None: + function() + of = "" + desc = "" + sep = " " + if not self is None: + if self.program: + of = " of " + self.program + sep = "\n\t" + if self.description: + desc = " [" + self.description + "]" + sep = "\n\t" + + at = _caller(traceback.extract_stack(), skip) + if message: + msg = "\t%s\n" % message + else: + msg = "" + sys.stderr.write("FAILED test" + of + desc + sep + at + msg) + + sys.exit(1) + + +def no_result(self=None, condition=1, function=None, skip=0): + """Causes a test to exit with no valid result. + + By default, the no_result() method reports NO RESULT for the test + and exits with a status of 2. If a condition argument is supplied, + the test fails only if the condition is true. + """ + if not condition: + return + if not function is None: + function() + of = "" + desc = "" + sep = " " + if not self is None: + if self.program: + of = " of " + self.program + sep = "\n\t" + if self.description: + desc = " [" + self.description + "]" + sep = "\n\t" + + at = _caller(traceback.extract_stack(), skip) + sys.stderr.write("NO RESULT for test" + of + desc + sep + at) + + sys.exit(2) + + +def pass_test(self=None, condition=1, function=None): + """Causes a test to pass. + + By default, the pass_test() method reports PASSED for the test + and exits with a status of 0. If a condition argument is supplied, + the test passes only if the condition is true. + """ + if not condition: + return + if not function is None: + function() + sys.stderr.write("PASSED\n") + sys.exit(0) + + +def match_exact(lines=None, matches=None, newline=os.sep): + """ + """ + + if isinstance(lines, bytes) or bytes is str: + newline = to_bytes(newline) + + if not is_List(lines): + lines = lines.split(newline) + if not is_List(matches): + matches = matches.split(newline) + if len(lines) != len(matches): + return + for i in range(len(lines)): + if lines[i] != matches[i]: + return + return 1 + + +def match_caseinsensitive(lines=None, matches=None): + """ + """ + if not is_List(lines): + lines = lines.split("\n") + if not is_List(matches): + matches = matches.split("\n") + if len(lines) != len(matches): + return + for i in range(len(lines)): + if lines[i].lower() != matches[i].lower(): + return + return 1 + + +def match_re(lines=None, res=None): + """ + """ + if not is_List(lines): + # CRs mess up matching (Windows) so split carefully + lines = re.split('\r?\n', lines) + if not is_List(res): + res = res.split("\n") + if len(lines) != len(res): + print("match_re: expected %d lines, found %d" % (len(res), len(lines))) + return + for i in range(len(lines)): + s = "^" + res[i] + "$" + try: + expr = re.compile(s) + except re.error as e: + msg = "Regular expression error in %s: %s" + raise re.error(msg % (repr(s), e.args[0])) + if not expr.search(lines[i]): + print("match_re: mismatch at line %d:\n search re='%s'\n line='%s'" % ( + i, s, lines[i])) + return + return 1 + + +def match_re_dotall(lines=None, res=None): + """ + """ + if not isinstance(lines, str): + lines = "\n".join(lines) + if not isinstance(res, str): + res = "\n".join(res) + s = "^" + res + "$" + try: + expr = re.compile(s, re.DOTALL) + except re.error as e: + msg = "Regular expression error in %s: %s" + raise re.error(msg % (repr(s), e.args[0])) + return expr.match(lines) + + +def simple_diff(a, b, fromfile='', tofile='', + fromfiledate='', tofiledate='', n=3, lineterm='\n'): + """ + A function with the same calling signature as difflib.context_diff + (diff -c) and difflib.unified_diff (diff -u) but which prints + output like the simple, unadorned 'diff" command. + """ + a = [to_str(q) for q in a] + b = [to_str(q) for q in b] + sm = difflib.SequenceMatcher(None, a, b) + + def comma(x1, x2): + return x1 + 1 == x2 and str(x2) or '%s,%s' % (x1 + 1, x2) + result = [] + for op, a1, a2, b1, b2 in sm.get_opcodes(): + if op == 'delete': + result.append("%sd%d" % (comma(a1, a2), b1)) + result.extend(['< ' + l for l in a[a1:a2]]) + elif op == 'insert': + result.append("%da%s" % (a1, comma(b1, b2))) + result.extend(['> ' + l for l in b[b1:b2]]) + elif op == 'replace': + result.append("%sc%s" % (comma(a1, a2), comma(b1, b2))) + result.extend(['< ' + l for l in a[a1:a2]]) + result.append('---') + result.extend(['> ' + l for l in b[b1:b2]]) + return result + + +def diff_re(a, b, fromfile='', tofile='', + fromfiledate='', tofiledate='', n=3, lineterm='\n'): + """ + A simple "diff" of two sets of lines when the expected lines + are regular expressions. This is a really dumb thing that + just compares each line in turn, so it doesn't look for + chunks of matching lines and the like--but at least it lets + you know exactly which line first didn't compare correctl... + """ + result = [] + diff = len(a) - len(b) + if diff < 0: + a = a + [''] * (-diff) + elif diff > 0: + b = b + [''] * diff + i = 0 + for aline, bline in zip(a, b): + s = "^" + aline + "$" + try: + expr = re.compile(s) + except re.error as e: + msg = "Regular expression error in %s: %s" + raise re.error(msg % (repr(s), e.args[0])) + if not expr.search(bline): + result.append("%sc%s" % (i + 1, i + 1)) + result.append('< ' + repr(a[i])) + result.append('---') + result.append('> ' + repr(b[i])) + i = i + 1 + return result + + +if os.name == 'posix': + def escape(arg): + "escape shell special characters" + slash = '\\' + special = '"$' + arg = arg.replace(slash, slash + slash) + for c in special: + arg = arg.replace(c, slash + c) + if re_space.search(arg): + arg = '"' + arg + '"' + return arg +else: + # Windows does not allow special characters in file names + # anyway, so no need for an escape function, we will just quote + # the arg. + def escape(arg): + if re_space.search(arg): + arg = '"' + arg + '"' + return arg + +if os.name == 'java': + python = os.path.join(sys.prefix, 'jython') +else: + python = os.environ.get('python_executable', sys.executable) +_python_ = escape(python) + +if sys.platform == 'win32': + + default_sleep_seconds = 2 + + def where_is(file, path=None, pathext=None): + if path is None: + path = os.environ['PATH'] + if is_String(path): + path = path.split(os.pathsep) + if pathext is None: + pathext = os.environ['PATHEXT'] + if is_String(pathext): + pathext = pathext.split(os.pathsep) + for ext in pathext: + if ext.lower() == file[-len(ext):].lower(): + pathext = [''] + break + for dir in path: + f = os.path.join(dir, file) + for ext in pathext: + fext = f + ext + if os.path.isfile(fext): + return fext + return None + +else: + + def where_is(file, path=None, pathext=None): + if path is None: + path = os.environ['PATH'] + if is_String(path): + path = path.split(os.pathsep) + for dir in path: + f = os.path.join(dir, file) + if os.path.isfile(f): + try: + st = os.stat(f) + except OSError: + continue + if stat.S_IMODE(st[stat.ST_MODE]) & 0o111: + return f + return None + + default_sleep_seconds = 1 + + +import subprocess + +try: + subprocess.Popen.terminate +except AttributeError: + if sys.platform == 'win32': + import win32process + + def terminate(self): + win32process.TerminateProcess(self._handle, 1) + else: + def terminate(self): + os.kill(self.pid, signal.SIGTERM) + method = types.MethodType(terminate, None, subprocess.Popen) + setattr(subprocess.Popen, 'terminate', method) + + +# From Josiah Carlson, +# ASPN : Python Cookbook : Module to allow Asynchronous subprocess use on Windows and Posix platforms +# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440554 + +PIPE = subprocess.PIPE + +if sys.platform == 'win32': # and subprocess.mswindows: + try: + from win32file import ReadFile, WriteFile + from win32pipe import PeekNamedPipe + except ImportError: + # If PyWin32 is not available, try ctypes instead + # XXX These replicate _just_enough_ PyWin32 behaviour for our purposes + import ctypes + from ctypes.wintypes import DWORD + + def ReadFile(hFile, bufSize, ol=None): + assert ol is None + lpBuffer = ctypes.create_string_buffer(bufSize) + bytesRead = DWORD() + bErr = ctypes.windll.kernel32.ReadFile( + hFile, lpBuffer, bufSize, ctypes.byref(bytesRead), ol) + if not bErr: + raise ctypes.WinError() + return (0, ctypes.string_at(lpBuffer, bytesRead.value)) + + def WriteFile(hFile, data, ol=None): + assert ol is None + bytesWritten = DWORD() + bErr = ctypes.windll.kernel32.WriteFile( + hFile, data, len(data), ctypes.byref(bytesWritten), ol) + if not bErr: + raise ctypes.WinError() + return (0, bytesWritten.value) + + def PeekNamedPipe(hPipe, size): + assert size == 0 + bytesAvail = DWORD() + bErr = ctypes.windll.kernel32.PeekNamedPipe( + hPipe, None, size, None, ctypes.byref(bytesAvail), None) + if not bErr: + raise ctypes.WinError() + return ("", bytesAvail.value, None) + import msvcrt +else: + import select + import fcntl + + try: + fcntl.F_GETFL + except AttributeError: + fcntl.F_GETFL = 3 + + try: + fcntl.F_SETFL + except AttributeError: + fcntl.F_SETFL = 4 + + +class Popen(subprocess.Popen): + def recv(self, maxsize=None): + return self._recv('stdout', maxsize) + + def recv_err(self, maxsize=None): + return self._recv('stderr', maxsize) + + def send_recv(self, input='', maxsize=None): + return self.send(input), self.recv(maxsize), self.recv_err(maxsize) + + def get_conn_maxsize(self, which, maxsize): + if maxsize is None: + maxsize = 1024 + elif maxsize < 1: + maxsize = 1 + return getattr(self, which), maxsize + + def _close(self, which): + getattr(self, which).close() + setattr(self, which, None) + + if sys.platform == 'win32': # and subprocess.mswindows: + def send(self, input): + input = to_bytes(input) + if not self.stdin: + return None + + try: + x = msvcrt.get_osfhandle(self.stdin.fileno()) + (errCode, written) = WriteFile(x, input) + except ValueError: + return self._close('stdin') + except (subprocess.pywintypes.error, Exception) as why: + if why.args[0] in (109, errno.ESHUTDOWN): + return self._close('stdin') + raise + + return written + + def _recv(self, which, maxsize): + conn, maxsize = self.get_conn_maxsize(which, maxsize) + if conn is None: + return None + + try: + x = msvcrt.get_osfhandle(conn.fileno()) + (read, nAvail, nMessage) = PeekNamedPipe(x, 0) + if maxsize < nAvail: + nAvail = maxsize + if nAvail > 0: + (errCode, read) = ReadFile(x, nAvail, None) + except ValueError: + return self._close(which) + except (subprocess.pywintypes.error, Exception) as why: + if why.args[0] in (109, errno.ESHUTDOWN): + return self._close(which) + raise + + # if self.universal_newlines: + # read = self._translate_newlines(read) + return read + + else: + def send(self, input): + if not self.stdin: + return None + + if not select.select([], [self.stdin], [], 0)[1]: + return 0 + + try: + written = os.write(self.stdin.fileno(), + bytearray(input, 'utf-8')) + except OSError as why: + if why.args[0] == errno.EPIPE: # broken pipe + return self._close('stdin') + raise + + return written + + def _recv(self, which, maxsize): + conn, maxsize = self.get_conn_maxsize(which, maxsize) + if conn is None: + return None + + try: + flags = fcntl.fcntl(conn, fcntl.F_GETFL) + except TypeError: + flags = None + else: + if not conn.closed: + fcntl.fcntl(conn, fcntl.F_SETFL, flags | os.O_NONBLOCK) + + try: + if not select.select([conn], [], [], 0)[0]: + return '' + + r = conn.read(maxsize) + if not r: + return self._close(which) + + # if self.universal_newlines: + # r = self._translate_newlines(r) + return r + finally: + if not conn.closed and not flags is None: + fcntl.fcntl(conn, fcntl.F_SETFL, flags) + + +disconnect_message = "Other end disconnected!" + + +def recv_some(p, t=.1, e=1, tr=5, stderr=0): + if tr < 1: + tr = 1 + x = time.time() + t + y = [] + r = '' + pr = p.recv + if stderr: + pr = p.recv_err + while time.time() < x or r: + r = pr() + if r is None: + if e: + raise Exception(disconnect_message) + else: + break + elif r: + y.append(r) + else: + time.sleep(max((x - time.time()) / tr, 0)) + return ''.join(y) + + +def send_all(p, data): + while len(data): + sent = p.send(data) + if sent is None: + raise Exception(disconnect_message) + data = memoryview(data)[sent:] + + +_Cleanup = [] + + +def _clean(): + global _Cleanup + cleanlist = [c for c in _Cleanup if c] + del _Cleanup[:] + cleanlist.reverse() + for test in cleanlist: + test.cleanup() + + +atexit.register(_clean) + + +class TestCmd(object): + """Class TestCmd + """ + + def __init__(self, description=None, + program=None, + interpreter=None, + workdir=None, + subdir=None, + verbose=None, + match=None, + match_stdout=None, + match_stderr=None, + diff=None, + diff_stdout=None, + diff_stderr=None, + combine=0, + universal_newlines=True, + timeout=None): + self.external = os.environ.get('SCONS_EXTERNAL_TEST', 0) + self._cwd = os.getcwd() + self.description_set(description) + self.program_set(program) + self.interpreter_set(interpreter) + if verbose is None: + try: + verbose = max(0, int(os.environ.get('TESTCMD_VERBOSE', 0))) + except ValueError: + verbose = 0 + self.verbose_set(verbose) + self.combine = combine + self.universal_newlines = universal_newlines + self.process = None + self.set_timeout(timeout) + self.set_match_function(match, match_stdout, match_stderr) + self.set_diff_function(diff, diff_stdout, diff_stderr) + self._dirlist = [] + self._preserve = {'pass_test': 0, 'fail_test': 0, 'no_result': 0} + preserve_value = os.environ.get('PRESERVE', False) + if preserve_value not in [0, '0', 'False']: + self._preserve['pass_test'] = os.environ['PRESERVE'] + self._preserve['fail_test'] = os.environ['PRESERVE'] + self._preserve['no_result'] = os.environ['PRESERVE'] + else: + try: + self._preserve['pass_test'] = os.environ['PRESERVE_PASS'] + except KeyError: + pass + try: + self._preserve['fail_test'] = os.environ['PRESERVE_FAIL'] + except KeyError: + pass + try: + self._preserve['no_result'] = os.environ['PRESERVE_NO_RESULT'] + except KeyError: + pass + self._stdout = [] + self._stderr = [] + self.status = None + self.condition = 'no_result' + self.workdir_set(workdir) + self.subdir(subdir) + self.fixture_dirs = [] + + def __del__(self): + self.cleanup() + + def __repr__(self): + return "%x" % id(self) + + banner_char = '=' + banner_width = 80 + + def banner(self, s, width=None): + if width is None: + width = self.banner_width + return s + self.banner_char * (width - len(s)) + + escape = staticmethod(escape) + + def canonicalize(self, path): + if is_List(path): + path = os.path.join(*tuple(path)) + if not os.path.isabs(path): + path = os.path.join(self.workdir, path) + return path + + def chmod(self, path, mode): + """Changes permissions on the specified file or directory + path name.""" + path = self.canonicalize(path) + os.chmod(path, mode) + + def cleanup(self, condition=None): + """Removes any temporary working directories for the specified + TestCmd environment. If the environment variable PRESERVE was + set when the TestCmd environment was created, temporary working + directories are not removed. If any of the environment variables + PRESERVE_PASS, PRESERVE_FAIL, or PRESERVE_NO_RESULT were set + when the TestCmd environment was created, then temporary working + directories are not removed if the test passed, failed, or had + no result, respectively. Temporary working directories are also + preserved for conditions specified via the preserve method. + + Typically, this method is not called directly, but is used when + the script exits to clean up temporary working directories as + appropriate for the exit status. + """ + if not self._dirlist: + return + os.chdir(self._cwd) + self.workdir = None + if condition is None: + condition = self.condition + if self._preserve[condition]: + for dir in self._dirlist: + print(u"Preserved directory " + dir + "\n") + else: + list = self._dirlist[:] + list.reverse() + for dir in list: + self.writable(dir, 1) + shutil.rmtree(dir, ignore_errors=1) + self._dirlist = [] + + global _Cleanup + if self in _Cleanup: + _Cleanup.remove(self) + + def command_args(self, program=None, + interpreter=None, + arguments=None): + if not self.external: + if program: + if isinstance(program, str) and not os.path.isabs(program): + program = os.path.join(self._cwd, program) + else: + program = self.program + if not interpreter: + interpreter = self.interpreter + else: + if not program: + program = self.program + if not interpreter: + interpreter = self.interpreter + if not isinstance(program, (list, tuple)): + program = [program] + cmd = list(program) + if interpreter: + if not isinstance(interpreter, (list, tuple)): + interpreter = [interpreter] + cmd = list(interpreter) + cmd + if arguments: + if isinstance(arguments, str): + arguments = arguments.split() + cmd.extend(arguments) + return cmd + + def description_set(self, description): + """Set the description of the functionality being tested. + """ + self.description = description + + def set_diff_function(self, diff=_Null, stdout=_Null, stderr=_Null): + """Sets the specified diff functions. + """ + if diff is not _Null: + self._diff_function = diff + if stdout is not _Null: + self._diff_stdout_function = stdout + if stderr is not _Null: + self._diff_stderr_function = stderr + + def diff(self, a, b, name=None, diff_function=None, *args, **kw): + if diff_function is None: + try: + diff_function = getattr(self, self._diff_function) + except TypeError: + diff_function = self._diff_function + if diff_function is None: + diff_function = self.simple_diff + if name is not None: + print(self.banner(name)) + + if not is_List(a): + a=a.splitlines() + if not is_List(b): + b=b.splitlines() + + args = (a, b) + args + for line in diff_function(*args, **kw): + print(line) + + def diff_stderr(self, a, b, *args, **kw): + """Compare actual and expected file contents. + """ + try: + diff_stderr_function = getattr(self, self._diff_stderr_function) + except TypeError: + diff_stderr_function = self._diff_stderr_function + return self.diff(a, b, diff_function=diff_stderr_function, *args, **kw) + + def diff_stdout(self, a, b, *args, **kw): + """Compare actual and expected file contents. + """ + try: + diff_stdout_function = getattr(self, self._diff_stdout_function) + except TypeError: + diff_stdout_function = self._diff_stdout_function + return self.diff(a, b, diff_function=diff_stdout_function, *args, **kw) + + simple_diff = staticmethod(simple_diff) + + diff_re = staticmethod(diff_re) + + context_diff = staticmethod(difflib.context_diff) + + unified_diff = staticmethod(difflib.unified_diff) + + def fail_test(self, condition=1, function=None, skip=0, message=None): + """Cause the test to fail. + """ + if not condition: + return + self.condition = 'fail_test' + fail_test(self=self, + condition=condition, + function=function, + skip=skip, + message=message) + + def interpreter_set(self, interpreter): + """Set the program to be used to interpret the program + under test as a script. + """ + self.interpreter = interpreter + + def set_match_function(self, match=_Null, stdout=_Null, stderr=_Null): + """Sets the specified match functions. + """ + if match is not _Null: + self._match_function = match + if stdout is not _Null: + self._match_stdout_function = stdout + if stderr is not _Null: + self._match_stderr_function = stderr + + def match(self, lines, matches): + """Compare actual and expected file contents. + """ + try: + match_function = getattr(self, self._match_function) + except TypeError: + match_function = self._match_function + if match_function is None: + # Default is regular expression matches. + match_function = self.match_re + return match_function(lines, matches) + + def match_stderr(self, lines, matches): + """Compare actual and expected file contents. + """ + try: + match_stderr_function = getattr(self, self._match_stderr_function) + except TypeError: + match_stderr_function = self._match_stderr_function + if match_stderr_function is None: + # Default is to use whatever match= is set to. + match_stderr_function = self.match + return match_stderr_function(lines, matches) + + def match_stdout(self, lines, matches): + """Compare actual and expected file contents. + """ + try: + match_stdout_function = getattr(self, self._match_stdout_function) + except TypeError: + match_stdout_function = self._match_stdout_function + if match_stdout_function is None: + # Default is to use whatever match= is set to. + match_stdout_function = self.match + return match_stdout_function(lines, matches) + + match_exact = staticmethod(match_exact) + + match_caseinsensitive = staticmethod(match_caseinsensitive) + + match_re = staticmethod(match_re) + + match_re_dotall = staticmethod(match_re_dotall) + + def no_result(self, condition=1, function=None, skip=0): + """Report that the test could not be run. + """ + if not condition: + return + self.condition = 'no_result' + no_result(self=self, + condition=condition, + function=function, + skip=skip) + + def pass_test(self, condition=1, function=None): + """Cause the test to pass. + """ + if not condition: + return + self.condition = 'pass_test' + pass_test(self=self, condition=condition, function=function) + + def preserve(self, *conditions): + """Arrange for the temporary working directories for the + specified TestCmd environment to be preserved for one or more + conditions. If no conditions are specified, arranges for + the temporary working directories to be preserved for all + conditions. + """ + if not conditions: + conditions = ('pass_test', 'fail_test', 'no_result') + for cond in conditions: + self._preserve[cond] = 1 + + def program_set(self, program): + """Set the executable program or script to be tested. + """ + if not self.external: + if program and not os.path.isabs(program): + program = os.path.join(self._cwd, program) + self.program = program + + def read(self, file, mode='rb', newline=None): + """Reads and returns the contents of the specified file name. + The file name may be a list, in which case the elements are + concatenated with the os.path.join() method. The file is + assumed to be under the temporary working directory unless it + is an absolute path name. The I/O mode for the file may + be specified; it must begin with an 'r'. The default is + 'rb' (binary read). + """ + file = self.canonicalize(file) + if mode[0] != 'r': + raise ValueError("mode must begin with 'r'") + if IS_PY3 and 'b' not in mode: + with open(file, mode, newline=newline) as f: + return f.read() + else: + with open(file, mode) as f: + return f.read() + + def rmdir(self, dir): + """Removes the specified dir name. + The dir name may be a list, in which case the elements are + concatenated with the os.path.join() method. The dir is + assumed to be under the temporary working directory unless it + is an absolute path name. + The dir must be empty. + """ + dir = self.canonicalize(dir) + os.rmdir(dir) + + def _timeout(self): + self.process.terminate() + self.timer.cancel() + self.timer = None + + def set_timeout(self, timeout): + self.timeout = timeout + self.timer = None + + def parse_path(self, path, suppress_current=False): + """Return a list with the single path components of path. + """ + head, tail = os.path.split(path) + result = [] + if not tail: + if head == path: + return [head] + else: + result.append(tail) + head, tail = os.path.split(head) + while head and tail: + result.append(tail) + head, tail = os.path.split(head) + result.append(head or tail) + result.reverse() + + return result + + def dir_fixture(self, srcdir, dstdir=None): + """Copies the contents of the specified folder srcdir from + the directory of the called script, to the current + working directory. + The srcdir name may be a list, in which case the elements are + concatenated with the os.path.join() method. The dstdir is + assumed to be under the temporary working directory, it gets + created automatically, if it does not already exist. + """ + + if srcdir and self.fixture_dirs and not os.path.isabs(srcdir): + for dir in self.fixture_dirs: + spath = os.path.join(dir, srcdir) + if os.path.isdir(spath): + break + else: + spath = srcdir + + if dstdir: + dstdir = self.canonicalize(dstdir) + else: + dstdir = '.' + + if dstdir != '.' and not os.path.exists(dstdir): + dstlist = self.parse_path(dstdir) + if len(dstlist) > 0 and dstlist[0] == ".": + dstlist = dstlist[1:] + for idx in range(len(dstlist)): + self.subdir(dstlist[:idx + 1]) + + if dstdir and self.workdir: + dstdir = os.path.join(self.workdir, dstdir) + + for entry in os.listdir(spath): + epath = os.path.join(spath, entry) + dpath = os.path.join(dstdir, entry) + if os.path.isdir(epath): + # Copy the subfolder + shutil.copytree(epath, dpath) + else: + shutil.copy(epath, dpath) + + def file_fixture(self, srcfile, dstfile=None): + """Copies the file srcfile from the directory of + the called script, to the current working directory. + The dstfile is assumed to be under the temporary working + directory unless it is an absolute path name. + If dstfile is specified its target directory gets created + automatically, if it does not already exist. + """ + srcpath, srctail = os.path.split(srcfile) + + if srcpath and (not self.fixture_dirs or os.path.isabs(srcpath)): + spath = srcfile + else: + for dir in self.fixture_dirs: + spath = os.path.join(dir, srcfile) + if os.path.isfile(spath): + break + + if not dstfile: + if srctail: + dpath = os.path.join(self.workdir, srctail) + else: + return + else: + dstpath, dsttail = os.path.split(dstfile) + if dstpath: + if not os.path.exists(os.path.join(self.workdir, dstpath)): + dstlist = self.parse_path(dstpath) + if len(dstlist) > 0 and dstlist[0] == ".": + dstlist = dstlist[1:] + for idx in range(len(dstlist)): + self.subdir(dstlist[:idx + 1]) + + dpath = os.path.join(self.workdir, dstfile) + shutil.copy(spath, dpath) + + def start(self, program=None, + interpreter=None, + arguments=None, + universal_newlines=None, + timeout=_Null, + **kw): + """ + Starts a program or script for the test environment. + + The specified program will have the original directory + prepended unless it is enclosed in a [list]. + """ + cmd = self.command_args(program, interpreter, arguments) + if self.verbose: + cmd_string = ' '.join([self.escape(c) for c in cmd]) + sys.stderr.write(cmd_string + "\n") + if universal_newlines is None: + universal_newlines = self.universal_newlines + + # On Windows, if we make stdin a pipe when we plan to send + # no input, and the test program exits before + # Popen calls msvcrt.open_osfhandle, that call will fail. + # So don't use a pipe for stdin if we don't need one. + stdin = kw.get('stdin', None) + if stdin is not None: + stdin = subprocess.PIPE + + combine = kw.get('combine', self.combine) + if combine: + stderr_value = subprocess.STDOUT + else: + stderr_value = subprocess.PIPE + + if timeout is _Null: + timeout = self.timeout + if timeout: + self.timer = threading.Timer(float(timeout), self._timeout) + self.timer.start() + + if IS_PY3 and sys.platform == 'win32': + # Set this otherwist stdout/stderr pipes default to + # windows default locale cp1252 which will throw exception + # if using non-ascii characters. + # For example test/Install/non-ascii-name.py + os.environ['PYTHONIOENCODING'] = 'utf-8' + + # It seems that all pythons up to py3.6 still set text mode if you set encoding. + # TODO: File enhancement request on python to propagate universal_newlines even + # if encoding is set.hg c + p = Popen(cmd, + stdin=stdin, + stdout=subprocess.PIPE, + stderr=stderr_value, + env=os.environ, + universal_newlines=False) + + self.process = p + return p + + @staticmethod + def fix_binary_stream(stream): + """ + Handle stdout/stderr from popen when we specify universal_newlines = False. + This will read from the pipes in binary mode, not decode the output, + and not convert line endings to \n. + We do this because in py3 (3.5) with universal_newlines=True, it will + choose the default system locale to decode the output, and this breaks unicode + output. Specifically breaking test/option--tree.py which outputs a unicode char. + + py 3.6 allows us to pass an encoding param to popen thus not requiring the decode + nor end of line handling, because we propagate universal_newlines as specified. + + TODO: Do we need to pass universal newlines into this function? + """ + + if not stream: + return stream + # TODO: Run full tests on both platforms and see if this fixes failures + # It seems that py3.6 still sets text mode if you set encoding. + elif sys.version_info[0] == 3:# TODO and sys.version_info[1] < 6: + stream = stream.decode('utf-8') + stream = stream.replace('\r\n', '\n') + elif sys.version_info[0] == 2: + stream = stream.replace('\r\n', '\n') + + return stream + + + def finish(self, popen=None, **kw): + """ + Finishes and waits for the process being run under control of + the specified popen argument, recording the exit status, + standard output and error output. + """ + if popen is None: + popen = self.process + stdout, stderr = popen.communicate() + + stdout = self.fix_binary_stream(stdout) + stderr = self.fix_binary_stream(stderr) + + if self.timer: + self.timer.cancel() + self.timer = None + self.status = popen.returncode + self.process = None + self._stdout.append(stdout or '') + self._stderr.append(stderr or '') + + def run(self, program=None, + interpreter=None, + arguments=None, + chdir=None, + stdin=None, + universal_newlines=None, + timeout=_Null): + """Runs a test of the program or script for the test + environment. Standard output and error output are saved for + future retrieval via the stdout() and stderr() methods. + + The specified program will have the original directory + prepended unless it is enclosed in a [list]. + """ + if self.external: + if not program: + program = self.program + if not interpreter: + interpreter = self.interpreter + + if universal_newlines is None: + universal_newlines = self.universal_newlines + + if chdir: + oldcwd = os.getcwd() + if not os.path.isabs(chdir): + chdir = os.path.join(self.workpath(chdir)) + if self.verbose: + sys.stderr.write("chdir(" + chdir + ")\n") + os.chdir(chdir) + p = self.start(program=program, + interpreter=interpreter, + arguments=arguments, + universal_newlines=universal_newlines, + timeout=timeout, + stdin=stdin) + if is_List(stdin): + stdin = ''.join(stdin) + + if stdin and IS_PY3:# and sys.version_info[1] < 6: + stdin = to_bytes(stdin) + + # TODO(sgk): figure out how to re-use the logic in the .finish() + # method above. Just calling it from here causes problems with + # subclasses that redefine .finish(). We could abstract this + # into Yet Another common method called both here and by .finish(), + # but that seems ill-thought-out. + stdout, stderr = p.communicate(input=stdin) + if self.timer: + self.timer.cancel() + self.timer = None + self.status = p.returncode + self.process = None + + stdout = self.fix_binary_stream(stdout) + stderr = self.fix_binary_stream(stderr) + + + self._stdout.append(stdout or '') + self._stderr.append(stderr or '') + + if chdir: + os.chdir(oldcwd) + if self.verbose >= 2: + write = sys.stdout.write + write('============ STATUS: %d\n' % self.status) + out = self.stdout() + if out or self.verbose >= 3: + write('============ BEGIN STDOUT (len=%d):\n' % len(out)) + write(out) + write('============ END STDOUT\n') + err = self.stderr() + if err or self.verbose >= 3: + write('============ BEGIN STDERR (len=%d)\n' % len(err)) + write(err) + write('============ END STDERR\n') + + def sleep(self, seconds=default_sleep_seconds): + """Sleeps at least the specified number of seconds. If no + number is specified, sleeps at least the minimum number of + seconds necessary to advance file time stamps on the current + system. Sleeping more seconds is all right. + """ + time.sleep(seconds) + + def stderr(self, run=None): + """Returns the error output from the specified run number. + If there is no specified run number, then returns the error + output of the last run. If the run number is less than zero, + then returns the error output from that many runs back from the + current run. + """ + if not run: + run = len(self._stderr) + elif run < 0: + run = len(self._stderr) + run + run = run - 1 + if run >= 0 and len(self._stderr) > run: + return self._stderr[run] + else: + '' + + def stdout(self, run=None): + """ + Returns the stored standard output from a given run. + + Args: + run: run number to select. If run number is omitted, + return the standard output of the most recent run. + If negative, use as a relative offset, so that -2 + means the run two prior to the most recent. + + Returns: + selected stdout string or None if there are no + stored runs. + """ + if not run: + run = len(self._stdout) + elif run < 0: + run = len(self._stdout) + run + run = run - 1 + if run >= 0 and len(self._stdout) > run: + return self._stdout[run] + else: + '' + + def subdir(self, *subdirs): + """Create new subdirectories under the temporary working + directory, one for each argument. An argument may be a list, + in which case the list elements are concatenated using the + os.path.join() method. Subdirectories multiple levels deep + must be created using a separate argument for each level: + + test.subdir('sub', ['sub', 'dir'], ['sub', 'dir', 'ectory']) + + Returns the number of subdirectories actually created. + """ + count = 0 + for sub in subdirs: + if sub is None: + continue + if is_List(sub): + sub = os.path.join(*tuple(sub)) + new = os.path.join(self.workdir, sub) + try: + os.mkdir(new) + except OSError as e: + print("Got error :%s"%e) + pass + else: + count = count + 1 + return count + + def symlink(self, target, link): + """Creates a symlink to the specified target. + The link name may be a list, in which case the elements are + concatenated with the os.path.join() method. The link is + assumed to be under the temporary working directory unless it + is an absolute path name. The target is *not* assumed to be + under the temporary working directory. + """ + if sys.platform == 'win32': + # Skip this on windows as we're not enabling it due to + # it requiring user permissions which aren't always present + # and we don't have a good way to detect those permissions yet. + return + link = self.canonicalize(link) + try: + os.symlink(target, link) + except AttributeError: + pass # Windows has no symlink + + def tempdir(self, path=None): + """Creates a temporary directory. + A unique directory name is generated if no path name is specified. + The directory is created, and will be removed when the TestCmd + object is destroyed. + """ + if path is None: + try: + path = tempfile.mktemp(prefix=tempfile.template) + except TypeError: + path = tempfile.mktemp() + os.mkdir(path) + + # Symlinks in the path will report things + # differently from os.getcwd(), so chdir there + # and back to fetch the canonical path. + cwd = os.getcwd() + try: + os.chdir(path) + path = os.getcwd() + finally: + os.chdir(cwd) + + # Uppercase the drive letter since the case of drive + # letters is pretty much random on win32: + drive, rest = os.path.splitdrive(path) + if drive: + path = drive.upper() + rest + + # + self._dirlist.append(path) + + global _Cleanup + if self not in _Cleanup: + _Cleanup.append(self) + + return path + + def touch(self, path, mtime=None): + """Updates the modification time on the specified file or + directory path name. The default is to update to the + current time if no explicit modification time is specified. + """ + path = self.canonicalize(path) + atime = os.path.getatime(path) + if mtime is None: + mtime = time.time() + os.utime(path, (atime, mtime)) + + def unlink(self, file): + """Unlinks the specified file name. + The file name may be a list, in which case the elements are + concatenated with the os.path.join() method. The file is + assumed to be under the temporary working directory unless it + is an absolute path name. + """ + file = self.canonicalize(file) + os.unlink(file) + + def verbose_set(self, verbose): + """Set the verbose level. + """ + self.verbose = verbose + + def where_is(self, file, path=None, pathext=None): + """Find an executable file. + """ + if is_List(file): + file = os.path.join(*tuple(file)) + if not os.path.isabs(file): + file = where_is(file, path, pathext) + return file + + def workdir_set(self, path): + """Creates a temporary working directory with the specified + path name. If the path is a null string (''), a unique + directory name is created. + """ + if (path != None): + if path == '': + path = None + path = self.tempdir(path) + self.workdir = path + + def workpath(self, *args): + """Returns the absolute path name to a subdirectory or file + within the current temporary working directory. Concatenates + the temporary working directory name with the specified + arguments using the os.path.join() method. + """ + return os.path.join(self.workdir, *tuple(args)) + + def readable(self, top, read=1): + """Make the specified directory tree readable (read == 1) + or not (read == None). + + This method has no effect on Windows systems, which use a + completely different mechanism to control file readability. + """ + + if sys.platform == 'win32': + return + + if read: + def do_chmod(fname): + try: + st = os.stat(fname) + except OSError: + pass + else: + os.chmod(fname, stat.S_IMODE( + st[stat.ST_MODE] | stat.S_IREAD)) + else: + def do_chmod(fname): + try: + st = os.stat(fname) + except OSError: + pass + else: + os.chmod(fname, stat.S_IMODE( + st[stat.ST_MODE] & ~stat.S_IREAD)) + + if os.path.isfile(top): + # If it's a file, that's easy, just chmod it. + do_chmod(top) + elif read: + # It's a directory and we're trying to turn on read + # permission, so it's also pretty easy, just chmod the + # directory and then chmod every entry on our walk down the + # tree. + do_chmod(top) + for dirpath, dirnames, filenames in os.walk(top): + for name in dirnames + filenames: + do_chmod(os.path.join(dirpath, name)) + else: + # It's a directory and we're trying to turn off read + # permission, which means we have to chmod the directories + # in the tree bottom-up, lest disabling read permission from + # the top down get in the way of being able to get at lower + # parts of the tree. + for dirpath, dirnames, filenames in os.walk(top, topdown=0): + for name in dirnames + filenames: + do_chmod(os.path.join(dirpath, name)) + do_chmod(top) + + def writable(self, top, write=1): + """Make the specified directory tree writable (write == 1) + or not (write == None). + """ + + if sys.platform == 'win32': + + if write: + def do_chmod(fname): + try: + os.chmod(fname, stat.S_IWRITE) + except OSError: + pass + else: + def do_chmod(fname): + try: + os.chmod(fname, stat.S_IREAD) + except OSError: + pass + + else: + + if write: + def do_chmod(fname): + try: + st = os.stat(fname) + except OSError: + pass + else: + os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE] | 0o200)) + else: + def do_chmod(fname): + try: + st = os.stat(fname) + except OSError: + pass + else: + os.chmod(fname, stat.S_IMODE( + st[stat.ST_MODE] & ~0o200)) + + if os.path.isfile(top): + do_chmod(top) + else: + do_chmod(top) + for dirpath, dirnames, filenames in os.walk(top, topdown=0): + for name in dirnames + filenames: + do_chmod(os.path.join(dirpath, name)) + + def executable(self, top, execute=1): + """Make the specified directory tree executable (execute == 1) + or not (execute == None). + + This method has no effect on Windows systems, which use a + completely different mechanism to control file executability. + """ + + if sys.platform == 'win32': + return + + if execute: + def do_chmod(fname): + try: + st = os.stat(fname) + except OSError: + pass + else: + os.chmod(fname, stat.S_IMODE( + st[stat.ST_MODE] | stat.S_IEXEC)) + else: + def do_chmod(fname): + try: + st = os.stat(fname) + except OSError: + pass + else: + os.chmod(fname, stat.S_IMODE( + st[stat.ST_MODE] & ~stat.S_IEXEC)) + + if os.path.isfile(top): + # If it's a file, that's easy, just chmod it. + do_chmod(top) + elif execute: + # It's a directory and we're trying to turn on execute + # permission, so it's also pretty easy, just chmod the + # directory and then chmod every entry on our walk down the + # tree. + do_chmod(top) + for dirpath, dirnames, filenames in os.walk(top): + for name in dirnames + filenames: + do_chmod(os.path.join(dirpath, name)) + else: + # It's a directory and we're trying to turn off execute + # permission, which means we have to chmod the directories + # in the tree bottom-up, lest disabling execute permission from + # the top down get in the way of being able to get at lower + # parts of the tree. + for dirpath, dirnames, filenames in os.walk(top, topdown=0): + for name in dirnames + filenames: + do_chmod(os.path.join(dirpath, name)) + do_chmod(top) + + def write(self, file, content, mode='wb'): + """Writes the specified content text (second argument) to the + specified file name (first argument). The file name may be + a list, in which case the elements are concatenated with the + os.path.join() method. The file is created under the temporary + working directory. Any subdirectories in the path must already + exist. The I/O mode for the file may be specified; it must + begin with a 'w'. The default is 'wb' (binary write). + """ + file = self.canonicalize(file) + if mode[0] != 'w': + raise ValueError("mode must begin with 'w'") + with open(file, mode) as f: + try: + f.write(content) + except TypeError as e: + # python 3 default strings are not bytes, but unicode + f.write(bytes(content, 'utf-8')) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/tools/gyp/testlib/SConsLib/TestCommon.py b/tools/gyp/testlib/SConsLib/TestCommon.py new file mode 100644 index 00000000000000..928900b34ea37c --- /dev/null +++ b/tools/gyp/testlib/SConsLib/TestCommon.py @@ -0,0 +1,760 @@ +""" +TestCommon.py: a testing framework for commands and scripts + with commonly useful error handling + +The TestCommon module provides a simple, high-level interface for writing +tests of executable commands and scripts, especially commands and scripts +that interact with the file system. All methods throw exceptions and +exit on failure, with useful error messages. This makes a number of +explicit checks unnecessary, making the test scripts themselves simpler +to write and easier to read. + +The TestCommon class is a subclass of the TestCmd class. In essence, +TestCommon is a wrapper that handles common TestCmd error conditions in +useful ways. You can use TestCommon directly, or subclass it for your +program and add additional (or override) methods to tailor it to your +program's specific needs. Alternatively, the TestCommon class serves +as a useful example of how to define your own TestCmd subclass. + +As a subclass of TestCmd, TestCommon provides access to all of the +variables and methods from the TestCmd module. Consequently, you can +use any variable or method documented in the TestCmd module without +having to explicitly import TestCmd. + +A TestCommon environment object is created via the usual invocation: + + import TestCommon + test = TestCommon.TestCommon() + +You can use all of the TestCmd keyword arguments when instantiating a +TestCommon object; see the TestCmd documentation for details. + +Here is an overview of the methods and keyword arguments that are +provided by the TestCommon class: + + test.must_be_writable('file1', ['file2', ...]) + + test.must_contain('file', 'required text\n') + + test.must_contain_all(output, input, ['title', find]) + + test.must_contain_all_lines(output, lines, ['title', find]) + + test.must_contain_any_line(output, lines, ['title', find]) + + test.must_contain_exactly_lines(output, lines, ['title', find]) + + test.must_exist('file1', ['file2', ...]) + + test.must_match('file', "expected contents\n") + + test.must_not_be_writable('file1', ['file2', ...]) + + test.must_not_contain('file', 'banned text\n') + + test.must_not_contain_any_line(output, lines, ['title', find]) + + test.must_not_exist('file1', ['file2', ...]) + + test.run(options = "options to be prepended to arguments", + stdout = "expected standard output from the program", + stderr = "expected error output from the program", + status = expected_status, + match = match_function) + +The TestCommon module also provides the following variables + + TestCommon.python + TestCommon._python_ + TestCommon.exe_suffix + TestCommon.obj_suffix + TestCommon.shobj_prefix + TestCommon.shobj_suffix + TestCommon.lib_prefix + TestCommon.lib_suffix + TestCommon.dll_prefix + TestCommon.dll_suffix + +""" + +# Copyright 2000-2010 Steven Knight +# This module is free software, and you may redistribute it and/or modify +# it under the same terms as Python itself, so long as this copyright message +# and disclaimer are retained in their original form. +# +# IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +# SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF +# THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. +# +# THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, +# AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, +# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +from __future__ import print_function + +__author__ = "Steven Knight " +__revision__ = "TestCommon.py 1.3.D001 2010/06/03 12:58:27 knight" +__version__ = "1.3" + +import os +import stat +import sys +import glob + +try: + from collections import UserList +except ImportError: + # no 'collections' module or no UserList in collections + exec('from UserList import UserList') + +from SConsLib.TestCmd import * +from SConsLib.TestCmd import __all__ + +__all__.extend([ 'TestCommon', + 'exe_suffix', + 'obj_suffix', + 'shobj_prefix', + 'shobj_suffix', + 'lib_prefix', + 'lib_suffix', + 'dll_prefix', + 'dll_suffix', + ]) + +# Variables that describe the prefixes and suffixes on this system. +if sys.platform == 'win32': + exe_suffix = '.exe' + obj_suffix = '.obj' + shobj_suffix = '.obj' + shobj_prefix = '' + lib_prefix = '' + lib_suffix = '.lib' + dll_prefix = '' + dll_suffix = '.dll' + module_prefix = '' + module_suffix = '.dll' +elif sys.platform == 'cygwin': + exe_suffix = '.exe' + obj_suffix = '.o' + shobj_suffix = '.os' + shobj_prefix = '' + lib_prefix = 'lib' + lib_suffix = '.a' + dll_prefix = 'cyg' + dll_suffix = '.dll' + module_prefix = '' + module_suffix = '.dll' +elif sys.platform.find('irix') != -1: + exe_suffix = '' + obj_suffix = '.o' + shobj_suffix = '.o' + shobj_prefix = '' + lib_prefix = 'lib' + lib_suffix = '.a' + dll_prefix = 'lib' + dll_suffix = '.so' + module_prefix = 'lib' + module_suffix = '.so' +elif sys.platform.find('darwin') != -1: + exe_suffix = '' + obj_suffix = '.o' + shobj_suffix = '.os' + shobj_prefix = '' + lib_prefix = 'lib' + lib_suffix = '.a' + dll_prefix = 'lib' + dll_suffix = '.dylib' + module_prefix = '' + module_suffix = '.so' +elif sys.platform.find('sunos') != -1: + exe_suffix = '' + obj_suffix = '.o' + shobj_suffix = '.o' + shobj_prefix = 'so_' + lib_prefix = 'lib' + lib_suffix = '.a' + dll_prefix = 'lib' + dll_suffix = '.so' + module_prefix = '' + module_suffix = '.so' +else: + exe_suffix = '' + obj_suffix = '.o' + shobj_suffix = '.os' + shobj_prefix = '' + lib_prefix = 'lib' + lib_suffix = '.a' + dll_prefix = 'lib' + dll_suffix = '.so' + module_prefix = 'lib' + module_suffix = '.so' + +def is_List(e): + return isinstance(e, (list, UserList)) + +def is_Tuple(e): + return isinstance(e, tuple) + +def is_Sequence(e): + return (not hasattr(e, "strip") and + hasattr(e, "__getitem__") or + hasattr(e, "__iter__")) + +def is_writable(f): + mode = os.stat(f)[stat.ST_MODE] + return mode & stat.S_IWUSR + +def separate_files(flist): + existing = [] + missing = [] + for f in flist: + if os.path.exists(f): + existing.append(f) + else: + missing.append(f) + return existing, missing + +def contains(seq, subseq, find): + # Returns True or False. + if find is None: + return subseq in seq + else: + f = find(seq, subseq) + return f not in (None, -1) and f is not False + +def find_index(seq, subseq, find): + # Returns either an index of the subseq within the seq, or None. + # Accepts a function find(seq, subseq), which returns an integer on success + # and either: None, False, or -1, on failure. + if find is None: + try: + return seq.index(subseq) + except ValueError: + return None + else: + i = find(seq, subseq) + return None if (i in (None, -1) or i is False) else i + + +if os.name == 'posix': + def _failed(self, status = 0): + if self.status is None or status is None: + return None + return _status(self) != status + def _status(self): + return self.status +elif os.name == 'nt': + def _failed(self, status = 0): + return not (self.status is None or status is None) and \ + self.status != status + def _status(self): + return self.status + +class TestCommon(TestCmd): + + # Additional methods from the Perl Test::Cmd::Common module + # that we may wish to add in the future: + # + # $test->subdir('subdir', ...); + # + # $test->copy('src_file', 'dst_file'); + + def __init__(self, **kw): + """Initialize a new TestCommon instance. This involves just + calling the base class initialization, and then changing directory + to the workdir. + """ + TestCmd.__init__(self, **kw) + os.chdir(self.workdir) + + def options_arguments(self, options, arguments): + """Merges the "options" keyword argument with the arguments.""" + if options: + if arguments is None: + return options + + # If not list, then split into lists + # this way we're not losing arguments specified with + # Spaces in quotes. + if isinstance(options, str): + options = options.split() + if isinstance(arguments, str): + arguments = arguments.split() + arguments = options + arguments + + return arguments + + def must_be_writable(self, *files): + """Ensures that the specified file(s) exist and are writable. + An individual file can be specified as a list of directory names, + in which case the pathname will be constructed by concatenating + them. Exits FAILED if any of the files does not exist or is + not writable. + """ + files = [is_List(x) and os.path.join(*x) or x for x in files] + existing, missing = separate_files(files) + unwritable = [x for x in existing if not is_writable(x)] + if missing: + print("Missing files: `%s'" % "', `".join(missing)) + if unwritable: + print("Unwritable files: `%s'" % "', `".join(unwritable)) + self.fail_test(missing + unwritable) + + def must_contain(self, file, required, mode='rb', find=None): + """Ensures specified file contains the required text. + + Args: + file (string): name of file to search in. + required (string): text to search for. For the default + find function, type must match the return type from + reading the file; current implementation will convert. + mode (string): file open mode. + find (func): optional custom search routine. Must take the + form "find(output, line)" non-negative integer on success + and None, False, or -1, on failure. + + Calling test exits FAILED if search result is false + """ + if 'b' in mode: + # Python 3: reading a file in binary mode returns a + # bytes object. We cannot find the index of a different + # (str) type in that, so convert. + required = to_bytes(required) + file_contents = self.read(file, mode) + + if not contains(file_contents, required, find): + print("File `%s' does not contain required string." % file) + print(self.banner('Required string ')) + print(required) + print(self.banner('%s contents ' % file)) + print(file_contents) + self.fail_test() + + def must_contain_all(self, output, input, title=None, find=None): + """Ensures that the specified output string (first argument) + contains all of the specified input as a block (second argument). + + An optional third argument can be used to describe the type + of output being searched, and only shows up in failure output. + + An optional fourth argument can be used to supply a different + function, of the form "find(output, line)", to use when searching + for lines in the output. + """ + if is_List(output): + output = os.newline.join(output) + + if not contains(output, input, find): + if title is None: + title = 'output' + print('Missing expected input from {}:'.format(title)) + print(input) + print(self.banner(title + ' ')) + print(output) + self.fail_test() + + def must_contain_all_lines(self, output, lines, title=None, find=None): + """Ensures that the specified output string (first argument) + contains all of the specified lines (second argument). + + An optional third argument can be used to describe the type + of output being searched, and only shows up in failure output. + + An optional fourth argument can be used to supply a different + function, of the form "find(output, line)", to use when searching + for lines in the output. + """ + missing = [] + if is_List(output): + output = '\n'.join(output) + + for line in lines: + if not contains(output, line, find): + missing.append(line) + + if missing: + if title is None: + title = 'output' + sys.stdout.write("Missing expected lines from %s:\n" % title) + for line in missing: + sys.stdout.write(' ' + repr(line) + '\n') + sys.stdout.write(self.banner(title + ' ') + '\n') + sys.stdout.write(output) + self.fail_test() + + def must_contain_any_line(self, output, lines, title=None, find=None): + """Ensures that the specified output string (first argument) + contains at least one of the specified lines (second argument). + + An optional third argument can be used to describe the type + of output being searched, and only shows up in failure output. + + An optional fourth argument can be used to supply a different + function, of the form "find(output, line)", to use when searching + for lines in the output. + """ + for line in lines: + if contains(output, line, find): + return + + if title is None: + title = 'output' + sys.stdout.write("Missing any expected line from %s:\n" % title) + for line in lines: + sys.stdout.write(' ' + repr(line) + '\n') + sys.stdout.write(self.banner(title + ' ') + '\n') + sys.stdout.write(output) + self.fail_test() + + def must_contain_exactly_lines(self, output, expect, title=None, find=None): + """Ensures that the specified output string (first argument) + contains all of the lines in the expected string (second argument) + with none left over. + + An optional third argument can be used to describe the type + of output being searched, and only shows up in failure output. + + An optional fourth argument can be used to supply a different + function, of the form "find(output, line)", to use when searching + for lines in the output. The function must return the index + of the found line in the output, or None if the line is not found. + """ + out = output.splitlines() + if is_List(expect): + exp = [ e.rstrip('\n') for e in expect ] + else: + exp = expect.splitlines() + if sorted(out) == sorted(exp): + # early out for exact match + return + missing = [] + for line in exp: + i = find_index(out, line, find) + if i is None: + missing.append(line) + else: + out.pop(i) + + if not missing and not out: + # all lines were matched + return + + if title is None: + title = 'output' + if missing: + sys.stdout.write("Missing expected lines from %s:\n" % title) + for line in missing: + sys.stdout.write(' ' + repr(line) + '\n') + sys.stdout.write(self.banner('Missing %s ' % title) + '\n') + if out: + sys.stdout.write("Extra unexpected lines from %s:\n" % title) + for line in out: + sys.stdout.write(' ' + repr(line) + '\n') + sys.stdout.write(self.banner('Extra %s ' % title) + '\n') + sys.stdout.flush() + self.fail_test() + + def must_contain_lines(self, lines, output, title=None, find = None): + # Deprecated; retain for backwards compatibility. + return self.must_contain_all_lines(output, lines, title, find) + + def must_exist(self, *files): + """Ensures that the specified file(s) must exist. An individual + file be specified as a list of directory names, in which case the + pathname will be constructed by concatenating them. Exits FAILED + if any of the files does not exist. + """ + files = [is_List(x) and os.path.join(*x) or x for x in files] + missing = [x for x in files if not os.path.exists(x) and not os.path.islink(x) ] + if missing: + print("Missing files: `%s'" % "', `".join(missing)) + self.fail_test(missing) + + def must_exist_one_of(self, files): + """Ensures that at least one of the specified file(s) exists. + The filenames can be given as a list, where each entry may be + a single path string, or a tuple of folder names and the final + filename that get concatenated. + Supports wildcard names like 'foo-1.2.3-*.rpm'. + Exits FAILED if none of the files exists. + """ + missing = [] + for x in files: + if is_List(x) or is_Tuple(x): + xpath = os.path.join(*x) + else: + xpath = is_Sequence(x) and os.path.join(x) or x + if glob.glob(xpath): + return + missing.append(xpath) + print("Missing one of: `%s'" % "', `".join(missing)) + self.fail_test(missing) + + def must_match(self, file, expect, mode = 'rb', match=None, message=None, newline=None): + """Matches the contents of the specified file (first argument) + against the expected contents (second argument). The expected + contents are a list of lines or a string which will be split + on newlines. + """ + file_contents = self.read(file, mode, newline) + if not match: + match = self.match + try: + self.fail_test(not match(to_str(file_contents), to_str(expect)), message=message) + except KeyboardInterrupt: + raise + except: + print("Unexpected contents of `%s'" % file) + self.diff(expect, file_contents, 'contents ') + raise + + def must_not_contain(self, file, banned, mode = 'rb', find = None): + """Ensures that the specified file doesn't contain the banned text. + """ + file_contents = self.read(file, mode) + + if contains(file_contents, banned, find): + print("File `%s' contains banned string." % file) + print(self.banner('Banned string ')) + print(banned) + print(self.banner('%s contents ' % file)) + print(file_contents) + self.fail_test() + + def must_not_contain_any_line(self, output, lines, title=None, find=None): + """Ensures that the specified output string (first argument) + does not contain any of the specified lines (second argument). + + An optional third argument can be used to describe the type + of output being searched, and only shows up in failure output. + + An optional fourth argument can be used to supply a different + function, of the form "find(output, line)", to use when searching + for lines in the output. + """ + unexpected = [] + for line in lines: + if contains(output, line, find): + unexpected.append(line) + + if unexpected: + if title is None: + title = 'output' + sys.stdout.write("Unexpected lines in %s:\n" % title) + for line in unexpected: + sys.stdout.write(' ' + repr(line) + '\n') + sys.stdout.write(self.banner(title + ' ') + '\n') + sys.stdout.write(output) + self.fail_test() + + def must_not_contain_lines(self, lines, output, title=None, find=None): + return self.must_not_contain_any_line(output, lines, title, find) + + def must_not_exist(self, *files): + """Ensures that the specified file(s) must not exist. + An individual file be specified as a list of directory names, in + which case the pathname will be constructed by concatenating them. + Exits FAILED if any of the files exists. + """ + files = [is_List(x) and os.path.join(*x) or x for x in files] + existing = [x for x in files if os.path.exists(x) or os.path.islink(x)] + if existing: + print("Unexpected files exist: `%s'" % "', `".join(existing)) + self.fail_test(existing) + + def must_not_exist_any_of(self, files): + """Ensures that none of the specified file(s) exists. + The filenames can be given as a list, where each entry may be + a single path string, or a tuple of folder names and the final + filename that get concatenated. + Supports wildcard names like 'foo-1.2.3-*.rpm'. + Exits FAILED if any of the files exists. + """ + existing = [] + for x in files: + if is_List(x) or is_Tuple(x): + xpath = os.path.join(*x) + else: + xpath = is_Sequence(x) and os.path.join(x) or x + if glob.glob(xpath): + existing.append(xpath) + if existing: + print("Unexpected files exist: `%s'" % "', `".join(existing)) + self.fail_test(existing) + + def must_not_be_writable(self, *files): + """Ensures that the specified file(s) exist and are not writable. + An individual file can be specified as a list of directory names, + in which case the pathname will be constructed by concatenating + them. Exits FAILED if any of the files does not exist or is + writable. + """ + files = [is_List(x) and os.path.join(*x) or x for x in files] + existing, missing = separate_files(files) + writable = [file for file in existing if is_writable(file)] + if missing: + print("Missing files: `%s'" % "', `".join(missing)) + if writable: + print("Writable files: `%s'" % "', `".join(writable)) + self.fail_test(missing + writable) + + def _complete(self, actual_stdout, expected_stdout, + actual_stderr, expected_stderr, status, match): + """ + Post-processes running a subcommand, checking for failure + status and displaying output appropriately. + """ + if _failed(self, status): + expect = '' + if status != 0: + expect = " (expected %s)" % str(status) + print("%s returned %s%s" % (self.program, _status(self), expect)) + print(self.banner('STDOUT ')) + print(actual_stdout) + print(self.banner('STDERR ')) + print(actual_stderr) + self.fail_test() + if (expected_stdout is not None + and not match(actual_stdout, expected_stdout)): + self.diff(expected_stdout, actual_stdout, 'STDOUT ') + if actual_stderr: + print(self.banner('STDERR ')) + print(actual_stderr) + self.fail_test() + if (expected_stderr is not None + and not match(actual_stderr, expected_stderr)): + print(self.banner('STDOUT ')) + print(actual_stdout) + self.diff(expected_stderr, actual_stderr, 'STDERR ') + self.fail_test() + + def start(self, program = None, + interpreter = None, + options = None, + arguments = None, + universal_newlines = None, + **kw): + """ + Starts a program or script for the test environment, handling + any exceptions. + """ + arguments = self.options_arguments(options, arguments) + try: + return TestCmd.start(self, program, interpreter, arguments, + universal_newlines, **kw) + except KeyboardInterrupt: + raise + except Exception as e: + print(self.banner('STDOUT ')) + try: + print(self.stdout()) + except IndexError: + pass + print(self.banner('STDERR ')) + try: + print(self.stderr()) + except IndexError: + pass + cmd_args = self.command_args(program, interpreter, arguments) + sys.stderr.write('Exception trying to execute: %s\n' % cmd_args) + raise e + + def finish(self, popen, stdout = None, stderr = '', status = 0, **kw): + """ + Finishes and waits for the process being run under control of + the specified popen argument. Additional arguments are similar + to those of the run() method: + + stdout The expected standard output from + the command. A value of None means + don't test standard output. + + stderr The expected error output from + the command. A value of None means + don't test error output. + + status The expected exit status from the + command. A value of None means don't + test exit status. + """ + TestCmd.finish(self, popen, **kw) + match = kw.get('match', self.match) + self._complete(self.stdout(), stdout, + self.stderr(), stderr, status, match) + + def run(self, options = None, arguments = None, + stdout = None, stderr = '', status = 0, **kw): + """Runs the program under test, checking that the test succeeded. + + The parameters are the same as the base TestCmd.run() method, + with the addition of: + + options Extra options that get prepended to the beginning + of the arguments. + + stdout The expected standard output from + the command. A value of None means + don't test standard output. + + stderr The expected error output from + the command. A value of None means + don't test error output. + + status The expected exit status from the + command. A value of None means don't + test exit status. + + By default, this expects a successful exit (status = 0), does + not test standard output (stdout = None), and expects that error + output is empty (stderr = ""). + """ + kw['arguments'] = self.options_arguments(options, arguments) + try: + match = kw['match'] + del kw['match'] + except KeyError: + match = self.match + TestCmd.run(self, **kw) + self._complete(self.stdout(), stdout, + self.stderr(), stderr, status, match) + + def skip_test(self, message="Skipping test.\n"): + """Skips a test. + + Proper test-skipping behavior is dependent on the external + TESTCOMMON_PASS_SKIPS environment variable. If set, we treat + the skip as a PASS (exit 0), and otherwise treat it as NO RESULT. + In either case, we print the specified message as an indication + that the substance of the test was skipped. + + (This was originally added to support development under Aegis. + Technically, skipping a test is a NO RESULT, but Aegis would + treat that as a test failure and prevent the change from going to + the next step. Since we ddn't want to force anyone using Aegis + to have to install absolutely every tool used by the tests, we + would actually report to Aegis that a skipped test has PASSED + so that the workflow isn't held up.) + """ + if message: + sys.stdout.write(message) + sys.stdout.flush() + pass_skips = os.environ.get('TESTCOMMON_PASS_SKIPS') + if pass_skips in [None, 0, '0']: + # skip=1 means skip this function when showing where this + # result came from. They only care about the line where the + # script called test.skip_test(), not the line number where + # we call test.no_result(). + self.no_result(skip=1) + else: + # We're under the development directory for this change, + # so this is an Aegis invocation; pass the test (exit 0). + self.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/tools/gyp/testlib/SConsLib/TestUnit/__init__.py b/tools/gyp/testlib/SConsLib/TestUnit/__init__.py new file mode 100644 index 00000000000000..51cf97208d1160 --- /dev/null +++ b/tools/gyp/testlib/SConsLib/TestUnit/__init__.py @@ -0,0 +1,5 @@ + +__all__ = ['TAPTestRunner', 'TAPTestResult', 'run'] + +from .taprunner import TAPTestRunner, TAPTestResult +from .cli import run diff --git a/tools/gyp/testlib/SConsLib/TestUnit/cli.py b/tools/gyp/testlib/SConsLib/TestUnit/cli.py new file mode 100644 index 00000000000000..f2a3b440d9519f --- /dev/null +++ b/tools/gyp/testlib/SConsLib/TestUnit/cli.py @@ -0,0 +1,32 @@ +""" +Choose test runner class from --runner command line option +and execute test cases. +""" + +import unittest +import optparse + +from SConsLib.TestUnit import TAPTestRunner + + +def get_runner(): + parser = optparse.OptionParser() + parser.add_option('--runner', default='unittest.TextTestRunner', + help='name of test runner class to use') + opts, args = parser.parse_args() + + fromsplit = opts.runner.rsplit('.', 1) + if len(fromsplit) < 2: + raise ValueError('Can\'t use module as a runner') + else: + runnermod = __import__(fromsplit[0]) + return getattr(runnermod, fromsplit[1]) + + +def run(): + runner = TAPTestRunner() + unittest.main(testRunner=runner) + + +if __name__ == '__main__': + run() diff --git a/tools/gyp/testlib/SConsLib/TestUnit/taprunner.py b/tools/gyp/testlib/SConsLib/TestUnit/taprunner.py new file mode 100644 index 00000000000000..5c2e87cd787b75 --- /dev/null +++ b/tools/gyp/testlib/SConsLib/TestUnit/taprunner.py @@ -0,0 +1,130 @@ +""" +Format unittest results in Test Anything Protocol (TAP). +http://testanything.org/tap-version-13-specification.html + +Public domain work by: + anatoly techtonik + +Changes: + 0.3 - fixed used imports that failed on Python 2.6 + 0.2 - removed unused import that failed on Python 2.6 + 0.1 - initial release +""" + +__version__ = "0.3" + + +from unittest import TextTestRunner +try: + from unittest import TextTestResult +except ImportError: + # Python 2.6 + from unittest import _TextTestResult as TextTestResult + + +class TAPTestResult(TextTestResult): + + def _process(self, test, msg, failtype = None, directive = None): + """ increase the counter, format and output TAP info """ + # counterhack: increase test counter + test.suite.tap_counter += 1 + msg = "%s %d" % (msg, test.suite.tap_counter) + if "not" not in msg: + msg += " " # justify + self.stream.write("%s - " % msg) + if failtype: + self.stream.write("%s - " % failtype) + self.stream.write("%s" % test.__class__.__name__) + self.stream.write(".%s" % test._testMethodName) + if directive: + self.stream.write(directive) + self.stream.write("\n") + # [ ] write test __doc__ (if exists) in comment + self.stream.flush() + + def addSuccess(self, test): + super(TextTestResult, self).addSuccess(test) + self._process(test, "ok") + + def addFailure(self, test, err): + super(TextTestResult, self).addFailure(test, err) + self._process(test, "not ok", "FAIL") + # [ ] add structured data about assertion + + def addError(self, test, err): + super(TextTestResult, self).addError(test, err) + self._process(test, "not ok", "ERROR") + # [ ] add structured data about exception + + def addSkip(self, test, reason): + super(TextTestResult, self).addSkip(test, reason) + self._process(test, "ok", directive=(" # SKIP %s" % reason)) + + def addExpectedFailure(self, test, err): + super(TextTestResult, self).addExpectedFailure(test, err) + self._process(test, "not ok", directive=(" # TODO")) + + def addUnexpectedSuccess(self, test): + super(TextTestResult, self).addUnexpectedSuccess(test) + self._process(test, "not ok", "FAIL (unexpected success)") + + """ + def printErrors(self): + def printErrorList(self, flavour, errors): + """ + + +class TAPTestRunner(TextTestRunner): + resultclass = TAPTestResult + + def run(self, test): + self.stream.write("TAP version 13\n") + # [ ] add commented block with test suite __doc__ + # [ ] check call with a single test + # if isinstance(test, suite.TestSuite): + self.stream.write("1..%s\n" % len(list(test))) + + # counterhack: inject test counter into test suite + test.tap_counter = 0 + # counterhack: inject reference to suite into each test case + for case in test: + case.suite = test + + return super(TAPTestRunner, self).run(test) + + +if __name__ == "__main__": + import sys + import unittest + + class Test(unittest.TestCase): + def test_ok(self): + pass + def test_fail(self): + self.assertTrue(False) + def test_error(self): + bad_symbol + @unittest.skip("skipin'") + def test_skip(self): + pass + @unittest.expectedFailure + def test_not_ready(self): + self.fail() + @unittest.expectedFailure + def test_invalid_fail_mark(self): + pass + def test_another_ok(self): + pass + + + suite = unittest.TestSuite([ + Test('test_ok'), + Test('test_fail'), + Test('test_error'), + Test('test_skip'), + Test('test_not_ready'), + Test('test_invalid_fail_mark'), + Test('test_another_ok') + ]) + if not TAPTestRunner().run(suite).wasSuccessful(): + sys.exit(1) diff --git a/tools/gyp/testlib/SConsLib/__init__.py b/tools/gyp/testlib/SConsLib/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/tools/gyp/testlib/TestGyp.py b/tools/gyp/testlib/TestGyp.py new file mode 100644 index 00000000000000..54e6442765f4f4 --- /dev/null +++ b/tools/gyp/testlib/TestGyp.py @@ -0,0 +1,1455 @@ +# 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. + +""" +TestGyp.py: a testing framework for GYP integration tests. +""" +from __future__ import print_function + +import collections +import errno +import itertools +import os +import re +import shutil +import subprocess +import sys +import tempfile +import json +import traceback + +from contextlib import contextmanager + +from SConsLib import TestCommon +from SConsLib.TestCmd import IS_PY3, is_List, match_re as test_cmd_match_re + +RPATH_RE = re.compile(r'Library (?:r|run)path: \[([^\]]+)\]') +RPROG_RE = re.compile(r'\[Requesting program interpreter: ([^\]]+)\]') +BUILDTOOLS_RE = re.compile(r"^xcode-select: error: tool 'xcodebuild' requires Xcode.*$\n", re.MULTILINE) +PYDEV_RE = re.compile(r"^pydev debugger.*$\n+", re.MULTILINE) + +def remove_debug_line_numbers(contents): + """Function to remove the line numbers from the debug output + of gyp and thus reduce the extreme fragility of the stdout + comparison tests. + """ + lines = contents.splitlines() + # split each line on first 4 ":" + lines = [l.split(":", 3) for l in lines] + # join each line back together while ignoring the + # 3rd column which is the line number + lines = [l[-1] for l in lines if len(l) > 3] + matches = [eval(l.split(':', 1)[1]) for l in lines if l.startswith('ExpandVariables Matches')] + matches = sorted([ + ' '.join(["%s=%s" % (k, d[k]) for k in sorted(d.keys())]) + for d in matches + ]) + found_output = sorted([l for l in lines if l.startswith('ExpandVariables Found output')]) + return '\n'.join(matches + found_output) + + +def match_modulo_line_numbers(contents_a, contents_b): + """File contents matcher that ignores line numbers.""" + return TestCommon.match_exact(contents_a, contents_b) + + +def mk_temp_dir(workdir): + # Put test output in out/testworkarea by default. + # Use temporary names so there are no collisions. + workdir = workdir or 'testworkarea' + workdir = os.path.join('out', workdir) + # Create work area if it doesn't already exist. + if not os.path.isdir(workdir): + os.makedirs(workdir) + return tempfile.mktemp(prefix='testgyp.', dir=workdir) + + +@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) + + +# noinspection PyAttributeOutsideInit +class TestGypBase(TestCommon.TestCommon): + """ + Class for controlling end-to-end tests of gyp generators. + + Instantiating this class will create a temporary directory and + arrange for its destruction (via the TestCmd superclass) and + copy all of the non-gyptest files in the directory hierarchy of the + executing script. + + The default behavior is to test the 'gyp' or 'gyp.bat' file in the + current directory. An alternative may be specified explicitly on + instantiation, or by setting the TESTGYP_GYP environment variable. + + This class should be subclassed for each supported gyp generator + (format). Various abstract methods below define calling signatures + used by the test scripts to invoke builds on the generated build + configuration and to run executables generated by those builds. + """ + + format = '' + formats = [] + build_tool = None + build_tool_list = [] + + _exe = TestCommon.exe_suffix + _obj = TestCommon.obj_suffix + shobj_ = TestCommon.shobj_prefix + _shobj = TestCommon.shobj_suffix + lib_ = TestCommon.lib_prefix + _lib = TestCommon.lib_suffix + dll_ = TestCommon.dll_prefix + _dll = TestCommon.dll_suffix + module_ = TestCommon.module_prefix + _module = TestCommon.module_suffix + + # Constants to represent different targets. + ALL = '__all__' + DEFAULT = '__default__' + + # Constants for different target types. + EXECUTABLE = '__executable__' + STATIC_LIB = '__static_lib__' + SHARED_LIB = '__shared_lib__' + LOADABLE_MODULE = '__loadable_module__' + + def __init__(self, gyp=None, **kw): + origin_cwd = os.path.abspath(os.path.dirname(sys.argv[0])) + + kw.setdefault('match', TestCommon.match_exact) + kw.setdefault('interpreter', sys.executable) + if 'description' not in kw: + bt = [t[0] for t in traceback.extract_stack() if 'gyptest' in t[0]] + kw['description'] = bt and bt.pop() + kw['workdir'] = mk_temp_dir(kw.get('workdir')) + kw_formats = kw.pop('formats', []) + + if not gyp: + gyp = os.environ.get('TESTGYP_GYP', 'gyp_main.py') + gyp = os.path.abspath(gyp) + kw.setdefault('program', gyp) + + super(TestGypBase, self).__init__(**kw) + + self.extra_args = sys.argv[1:] + self.origin_cwd=origin_cwd + self.gyp = gyp + + self.formats = [self.format] + + self.initialize_build_tool() + + if kw_formats: + excluded_formats = {f[1:] for f in kw_formats if f[0] == '!'} + explicit_formats = {f for f in kw_formats if f[0] != '!'} + possible_formats = set([self.format] + self.format.split('-')) + if excluded_formats.intersection(possible_formats): + self.skip_test('Test excluded for %s format' % self.format) + if explicit_formats and not explicit_formats.intersection(possible_formats): + self.skip_test('Test format %s not explicitly included' % self.format) + + self.dir_fixture(self.origin_cwd) + self.set_configuration(None) + self.is_make = 'make' in self.format.split('-') + self.is_ninja = 'ninja' in self.format.split('-') + + # Set $HOME so that gyp doesn't read the user's actual + # ~/.gyp/include.gypi file, which may contain variables + # and other settings that would change the output. + os.environ['HOME'] = self.workpath() + # 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 __del__(self): + return + + def _complete(self, actual_stdout, expected_stdout, actual_stderr, expected_stderr, status, match): + if sys.platform == 'darwin' and actual_stderr: + actual_stderr = BUILDTOOLS_RE.sub('', actual_stderr) + if actual_stderr: + actual_stderr = PYDEV_RE.sub('', actual_stderr) + if match.__name__ == 'match_modulo_line_numbers': + if actual_stdout: + actual_stdout = remove_debug_line_numbers(actual_stdout) + if expected_stdout: + expected_stdout = remove_debug_line_numbers(expected_stdout) + return super(TestGypBase, self)._complete(actual_stdout, expected_stdout, actual_stderr, expected_stderr, status, match) + + def built_file_must_exist(self, name, type=None, remove=False, **kw): + """ + Fails the test if the specified built file name does not exist. + """ + path = self.built_file_path(name, type, **kw) + self.must_exist(path) + if remove: + os.remove(path) + + def built_file_must_not_exist(self, name, type=None, **kw): + """ + Fails the test if the specified built file name exists. + """ + return self.must_not_exist(self.built_file_path(name, type, **kw)) + + def built_file_must_match(self, name, contents, **kw): + """ + Fails the test if the contents of the specified built file name + do not match the specified contents. + """ + return self.must_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 cleanup(self, condition=None): + os.chdir(self._cwd) + self.workdir = None + if not self._dirlist: + return + if self._preserve.get(condition or self.condition): + if self.verbose: + for d in self._dirlist: + print(u"Preserved directory %s" % d, file=sys.stderr) + return + lst = self._dirlist[:] + lst.reverse() + for d in lst: + self.writable(d, 1) + shutil.rmtree(d, ignore_errors=True) + self._dirlist = [] + # noinspection PyProtectedMember + from SConsLib.TestCmd import _Cleanup + if self in _Cleanup: + _Cleanup.remove(self) + + def fail_test(self, condition=1, function=None, skip=0, message=None): + """Cause the test to fail. + + By default, the fail_test() method reports that the test FAILED + and exits with a status of 1. If a condition argument is supplied, + the test fails only if the condition is true. + """ + if not condition: + return + self.condition = 'fail_test' + if not function is None: + function() + of = "" + desc = "" + sep = "" + if self.program: + of = " of " + self.program + sep = "\n" + if self.description: + desc = " [" + self.description + "]" + sep = "\n" + + string = "" + tb = [t for t in traceback.extract_stack() if os.path.basename(t[0]) not in ("TestCmd.py", "TestCommon.py", "TestGyp.py")] + for file, line, name, text in tb[skip:]: + if name not in ("?", ""): + name = " (" + name + ")" + string += ("%s:%d at %s\n" % (file, line, name)) + sys.stderr.flush() + sys.stderr.write("FAILED test:\n" + of + desc + sep) + sys.stderr.write(string) + sys.stderr.flush() + + sys.exit(1) + + def initialize_build_tool(self): + """ + Initializes the .build_tool attribute. + + Searches the .build_tool_list for an executable name on the user's + $PATH. The first tool on the list is used as-is if nothing is found + on the current $PATH. + """ + for build_tool in self.build_tool_list: + if not build_tool: + continue + if os.path.isabs(build_tool): + self.build_tool = build_tool + return + build_tool = self.where_is(build_tool) + if build_tool: + self.build_tool = build_tool + return + + if self.build_tool_list: + self.build_tool = self.build_tool_list[0] + + def must_match(self, file, expect, mode='rt', match=None, message=None, newline=None): + super(TestGypBase, self).must_match(file, expect, mode, match, message, newline) + + def must_contain(self, file, required, mode='rt', find=None): + if isinstance(required, list) and not find: + def find(content, subseq): + seq = content.splitlines() + seq_len = len(seq) + seq_strp = [l.strip() for l in seq] + sub_len = len(subseq) + subseq_strp = [l.strip() for l in subseq] + return any(seq_strp[i:i+sub_len] == subseq_strp for i in range(seq_len)) + super(TestGypBase, self).must_contain(file, required, mode, find) + + def must_not_contain(self, file, banned, mode='rt', find=None): + super(TestGypBase, self).must_not_contain(file, banned, mode, find) + + def read(self, file, mode='rt', newline=None, encoding='utf-8'): + file = self.canonicalize(file) + if mode[0] != 'r': + raise ValueError("mode must begin with 'r'") + kw = { + 'mode': mode, + } + if IS_PY3 and 'b' not in mode: + kw['encoding'] = encoding + kw['newline'] = newline + elif newline is None: + kw['mode'] = kw['mode'].replace('t', 'U') + + with open(file, **kw) as f: + ret = f.read() + + if not IS_PY3 and 'b' not in mode: + ret = ret.encode(encoding) + + return ret + + def relocate(self, source, destination): + """ + Renames (relocates) the specified source (usually a directory) + to the specified destination, creating the destination directory + first if necessary. + + Note: Don't use this as a generic "rename" operation. In the + future, "relocating" parts of a GYP tree may affect the state of + the test to modify the behavior of later method calls. + """ + destination_dir = os.path.dirname(destination) + if not os.path.exists(destination_dir): + self.subdir(destination_dir) + os.rename(source, destination) + + def report_not_up_to_date(self): + """ + Reports that a build is not up-to-date. + + This provides common reporting for formats that have complicated + conditions for checking whether a build is up-to-date. Formats + that expect exact output from the command (make) can + just set stdout= when they call the run_build() method. + """ + print("Build is not up-to-date:") + print(self.banner('STDOUT ')) + print(self.stdout()) + stderr = self.stderr() + if stderr: + print(self.banner('STDERR ')) + print(stderr) + + def run_gyp(self, gyp_file, *args, **kw): + """ + Runs gyp against the specified gyp_file with the specified args. + """ + if kw.pop('ignore_line_numbers', False): + kw.setdefault('match', match_modulo_line_numbers) + + # TODO: --depth=. works around Chromium-specific tree climbing. + depth = kw.pop('depth', '.') + run_args = ['--depth='+depth] + run_args.extend(['--format=' + f.replace('-mock', '') for f in self.formats]) + run_args.append(gyp_file) + + 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', '.*') + if self is TestGypXcodeNinja: + run_args.extend(['-G', 'xcode_ninja_target_pattern=%s' % xcode_ninja_target_pattern]) + + # TODO: if extra_args contains a '--build' flag we really want that to only apply to the last format (self.format). + run_args.extend(args) + + if 'mock' in self.format and any('--build' in a for a in run_args): + self.skip_test("--build skipped for 'mock' formats") + + return self.run(program=self.gyp, interpreter=self.interpreter, arguments=run_args, **kw) + + def run(self, *args, **kw): + """ + Executes a program by calling the superclass .run() method. + + This exists to provide a common place to filter out keyword + arguments implemented in this layer, without having to update + the tool-specific subclasses or clutter the tests themselves + with platform-specific code. + """ + if 'SYMROOT' in kw: + del kw['SYMROOT'] + return super(TestGypBase, self).run(*args, **kw) + + 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() + build_dir = 'build' if self.format == 'xcode' else 'out' + os.environ['DYLD_LIBRARY_PATH'] = os.path.join(build_dir, configuration) + return self.run(program=program, *args, **kw) + + def set_configuration(self, configuration): + """ + Sets the configuration, to be used for invoking the build + tool and testing potential built output. + """ + self.configuration = configuration + + def configuration_dirname(self): + if self.configuration: + return self.configuration.split('|')[0] + else: + return 'Default' + + def configuration_platform(self): + if self.configuration and '|' in self.configuration: + return self.configuration.split('|')[1] + else: + return '' + + def configuration_buildname(self): + if self.configuration: + return self.configuration + else: + return 'Default' + + + def no_result(self, condition=1, function=None, skip=0): + """ + Report that the test could not be run. + """ + if skip: + sys.exit(2) + else: + super(TestGypBase, self).no_result(condition, function, skip) + + def run_readelf(self, p, chdir='', flag='-d'): + r = RPATH_RE if flag == '-d' else RPROG_RE + p = self.built_file_path(p, chdir=chdir) + o = subprocess.check_output(['readelf', flag, p]).decode('utf-8') + return r.findall(o) + + + # + # Abstract methods to be defined by format-specific subclasses. + # + + def build(self, gyp_file, target=None, **kw): + """ + Runs a build of the specified target against the configuration + generated from the specified gyp_file. + + A 'target' argument of None or the special value TestGyp.DEFAULT + specifies the default argument for the underlying build tool. + A 'target' argument of TestGyp.ALL specifies the 'all' target + (if any) of the underlying build tool. + """ + raise NotImplementedError + + def built_file_path(self, name, type=None, **kw): + """ + Returns a path to the specified file name, of the specified type. + """ + raise NotImplementedError + + def built_file_basename(self, name, type=None, **kw): + """ + Returns the base name of the specified file name, of the specified type. + + A bare=True keyword argument specifies that prefixes and suffixes shouldn't + be applied. + """ + if not kw.get('bare'): + if type == self.EXECUTABLE: + name = name + self._exe + elif type == self.STATIC_LIB: + name = self.lib_ + name + self._lib + elif type == self.SHARED_LIB: + name = self.dll_ + name + self._dll + elif type == self.LOADABLE_MODULE: + name = self.module_ + name + self._module + return name + + def up_to_date(self, gyp_file, target=None, **kw): + """ + Verifies that a build of the specified target is up to date. + + The subclass should implement this by calling build() + (or a reasonable equivalent), checking whatever conditions + will tell it the build was an "up to date" null build, and + failing if it isn't. + """ + raise NotImplementedError + + +class TestGypGypd(TestGypBase): + """ + Subclass for testing the GYP 'gypd' generator (spit out the + internal data structure as pretty-printed Python). + """ + format = 'gypd' + + +class TestGypCustom(TestGypBase): + """ + Subclass for testing the GYP with custom generator + """ + + def __init__(self, **kw): + self.format = kw.pop("format") + super(TestGypCustom, self).__init__(**kw) + + +class TestGypCMake(TestGypBase): + """ + Subclass for testing the GYP CMake generator, using cmake's ninja backend. + """ + format = 'cmake' + build_tool_list = ['cmake'] + ALL = 'all' + + def cmake_build(self, **kw): + arguments = kw.get('arguments', [])[:] + + self.build_tool_list = ['cmake'] + self.initialize_build_tool() + + chdir = os.path.join(kw.get('chdir', '.'), 'out', self.configuration_dirname()) + kw['chdir'] = chdir + + arguments.append('-G') + arguments.append('Ninja') + + kw['arguments'] = arguments + + stderr = kw.get('stderr', None) + if stderr: + kw['stderr'] = stderr.split('$$$')[0] + + self.run(program=self.build_tool, **kw) + + def ninja_build(self, _, target=None, **kw): + arguments = kw.get('arguments', [])[:] + + self.build_tool_list = ['ninja'] + self.initialize_build_tool() + + # Add a -C output/path to the command line. + arguments.append('-C') + arguments.append(os.path.join('out', self.configuration_dirname())) + + if target not in (None, self.DEFAULT): + arguments.append(target) + + kw['arguments'] = arguments + + stderr = kw.get('stderr', None) + if stderr: + stderrs = stderr.split('$$$') + kw['stderr'] = stderrs[1] if len(stderrs) > 1 else '' + + return self.run(program=self.build_tool, **kw) + + 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(**kw) + kw['status'] = status + self.ninja_build(gyp_file, target, **kw) + + 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): + 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 + + +class TestGypMake(TestGypBase): + """ + Subclass for testing the GYP Make generator. + """ + format = 'make' + build_tool_list = ['make'] + ALL = 'all' + def build(self, gyp_file, target=None, **kw): + """ + Runs a Make build using the Makefiles generated from the specified + gyp_file. + """ + arguments = kw.get('arguments', [])[:] + if self.configuration: + arguments.append('BUILDTYPE=' + self.configuration) + if target not in (None, self.DEFAULT): + arguments.append(target) + # Sub-directory builds provide per-gyp Makefiles (i.e. + # Makefile.gyp_filename), so use that if there is no Makefile. + chdir = kw.get('chdir', '') + if not os.path.exists(os.path.join(chdir, 'Makefile')): + print("NO Makefile in " + os.path.join(chdir, 'Makefile')) + arguments.insert(0, '-f') + arguments.insert(1, os.path.splitext(gyp_file)[0] + '.Makefile') + kw['arguments'] = arguments + return self.run(program=self.build_tool, **kw) + + def up_to_date(self, gyp_file, target=None, **kw): + """ + Verifies that a build of the specified Make target is up to date. + """ + if target in (None, self.DEFAULT): + message_target = 'all' + else: + message_target = target + kw['stdout'] = "make: Nothing to be done for ['`]%s'.\n" % message_target + kw['match'] = test_cmd_match_re + return self.build(gyp_file, target, **kw) + + def run_built_executable(self, name, *args, **kw): + """ + Runs an executable built by Make. + """ + configuration = self.configuration_dirname() + libdir = os.path.join('out', configuration, 'lib') + # TODO(piman): when everything is cross-compile safe, remove lib.target + if sys.platform == 'darwin': + # Mac puts target shared libraries right in the product directory. + configuration = self.configuration_dirname() + os.environ['DYLD_LIBRARY_PATH'] = ( + libdir + '.host:' + os.path.join('out', configuration)) + else: + os.environ['LD_LIBRARY_PATH'] = libdir + '.host:' + libdir + '.target' + # 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) + + def built_file_path(self, name, type=None, **kw): + """ + Returns a path to the specified file name, of the specified type, + as built by Make. + + Built files are in the subdirectory 'out/{configuration}'. + The default is 'out/Default'. + + A chdir= keyword argument specifies the source directory + relative to which the output subdirectory can be found. + + "type" values of STATIC_LIB or SHARED_LIB append the necessary + prefixes and suffixes to a platform-independent library base name. + + A subdir= keyword argument specifies a library subdirectory within + the default 'obj.target'. + """ + result = [] + chdir = kw.get('chdir') + if chdir: + result.append(chdir) + configuration = self.configuration_dirname() + result.extend(['out', configuration]) + if type == self.STATIC_LIB and sys.platform != 'darwin': + result.append('obj.target') + elif type == self.SHARED_LIB and sys.platform != 'darwin': + 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 ConvertToCygpath(path): + """Convert to cygwin path if we are using cygwin.""" + if sys.platform == 'cygwin': + p = subprocess.Popen(['cygpath', path], stdout=subprocess.PIPE) + path = p.communicate()[0].strip() + return path + + +def MakeDirs(new_dir): + """A wrapper around os.makedirs() that emulates "mkdir -p".""" + try: + os.makedirs(new_dir) + except OSError as e: + if e.errno != errno.EEXIST: + raise + +def GetDefaultKeychainPath(): + """Get the keychain path, for used before updating HOME.""" + assert sys.platform == 'darwin' + # Format is: + # $ security default-keychain + # "/Some/Path/To/default.keychain" + path = subprocess.check_output(['security', 'default-keychain']).decode( + 'utf-8', 'ignore').strip() + return path[1:-1] + +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. + """ + from gyp.MSVS.MSVSVersion import TryQueryRegistryValue + + msvs_to_msbuild = { + '2015': '14.0', + '2013': '12.0', + '2012': '4.0', # Really v4.0.30319 which comes with .NET 4.5. + '2010': '4.0' + } + + msbuild_base_key = r'SOFTWARE\Microsoft\MSBuild\ToolsVersions' + if not TryQueryRegistryValue(msbuild_base_key): + print('Error: could not find MSBuild base registry entry') + return None + + msbuild_key = '' + found_msbuild_ver = '' + if msvs_version in msvs_to_msbuild: + msbuild_test_version = msvs_to_msbuild[msvs_version] + msbuild_key = msbuild_base_key + '\\' + msbuild_test_version + if TryQueryRegistryValue(msbuild_key): + found_msbuild_ver = msbuild_test_version + else: + print('Warning: Environment variable GYP_MSVS_VERSION specifies "%s" but corresponding MSBuild "%s" was not found.' % (msvs_version, found_msbuild_ver)) + if not found_msbuild_ver: + for msvs_version in sorted(msvs_to_msbuild.keys(), reverse=True): + msbuild_test_version = msvs_to_msbuild[msvs_version] + msbuild_key = msbuild_base_key + '\\' + msbuild_test_version + if TryQueryRegistryValue(msbuild_key): + found_msbuild_ver = msbuild_test_version + break + if not found_msbuild_ver: + print('Error: could not find am MSBuild registry entry') + return None + + msbuild_path = TryQueryRegistryValue(msbuild_key, 'MSBuildToolsPath') + if not msbuild_path: + print('Error: could not get MSBuildToolsPath registry entry value for MSBuild version %s' % found_msbuild_ver) + 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. + + We use the value specified by GYP_MSVS_VERSION. If not specified, we + search for likely deployment paths. + """ + override_build_tool = os.environ.get('GYP_BUILD_TOOL') + if override_build_tool: + return override_build_tool, True, override_build_tool + + msvs_version = 'auto' + for flag in (f for f in sys.argv if f.startswith('msvs_version=')): + msvs_version = flag.split('=')[-1] + msvs_version = os.environ.get('GYP_MSVS_VERSION', msvs_version) + + if msvs_version == 'auto' or msvs_version >= '2017': + msbuild_exes = [] + try: + args1 = [ + r'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe', + '-latest', '-products', '*', '-prerelease', '-format', 'json', + '-requires', 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', + ] + vswhere_json = subprocess.check_output(args1) + vswhere_infos = json.loads(vswhere_json) + if len(vswhere_infos) == 0: + raise IOError("vswhere did not find any MSVS instances.") + top_vs_info = vswhere_infos[0] + if top_vs_info: + inst_path = top_vs_info['installationPath'] + args2 = ['cmd.exe', '/d', '/c', + 'cd', '/d', inst_path, + '&', 'dir', '/b', '/s', 'msbuild.exe'] + msbuild_exes = subprocess.check_output(args2).strip().splitlines() + if len(msbuild_exes): + msbuild_path = str(msbuild_exes[0].decode('utf-8')) + os.environ['GYP_MSVS_VERSION'] = str(top_vs_info['catalog']['productLineVersion']) + os.environ['GYP_BUILD_TOOL'] = msbuild_path + return msbuild_path, True, msbuild_path + except Exception as e: + traceback.print_exc(file=sys.stderr) + print(e, file=sys.stderr) + pass + + possible_roots = ['%s:\\Program Files%s' % (chr(drive), suffix) + for drive in range(ord('C'), ord('Z') + 1) + for suffix in ['', ' (x86)']] + possible_paths = { + '2015': r'Microsoft Visual Studio 14.0\Common7\IDE\devenv.com', + '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', + '2005': r'Microsoft Visual Studio 8\Common7\IDE\devenv.com'} + + possible_roots = [ConvertToCygpath(r) for r in possible_roots] + + # Check that the path to the specified GYP_MSVS_VERSION exists. + if msvs_version in possible_paths: + path = possible_paths[msvs_version] + for r in possible_roots: + build_tool = os.path.join(r, path) + if os.path.exists(build_tool): + uses_msbuild = msvs_version >= '2010' + 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)) + print('Error: could not find MSVS version %s' % msvs_version) + sys.exit(1) + + +class TestGypOnMSToolchain(TestGypBase): + """ + Common subclass for testing generators that target the Microsoft Visual + Studio toolchain (cl, link, dumpbin, etc.) + """ + @staticmethod + def _ComputeVsvarsPath(devenv_path): + # devenv_dir = os.path.split(devenv_path)[0] + + # Check for location of Community install (in VS2017, at least). + vcvars_path = os.path.join(devenv_path, '..', '..', '..', '..', 'VC', 'Auxiliary', 'Build', 'vcvars32.bat') + if os.path.exists(vcvars_path): + return os.path.abspath(vcvars_path) + + vsvars_path = os.path.join(devenv_path, '..', '..', 'Tools', 'vsvars32.bat') + return os.path.abspath(vsvars_path) + + # noinspection PyAttributeOutsideInit + def initialize_build_tool(self): + super(TestGypOnMSToolchain, self).initialize_build_tool() + if sys.platform in ('win32', 'cygwin'): + build_tools = FindVisualStudioInstallation() + self.devenv_path, self.uses_msbuild, self.msbuild_path = build_tools + self.vsvars_path = TestGypOnMSToolchain._ComputeVsvarsPath(self.devenv_path) + + def run_dumpbin(self, *dumpbin_args): + """Run the dumpbin tool with the specified arguments, and capturing and + returning stdout.""" + assert sys.platform in ('win32', 'cygwin') + cmd = os.environ.get('COMSPEC', 'cmd.exe') + arguments = [cmd, '/c', self.vsvars_path, '&&', 'dumpbin'] + arguments.extend(dumpbin_args) + proc = subprocess.Popen(arguments, stdout=subprocess.PIPE) + output = proc.communicate()[0].decode('utf-8', 'ignore') + assert not proc.returncode + return output + + +class TestGypNinja(TestGypOnMSToolchain): + """ + Subclass for testing the GYP Ninja generator. + """ + format = 'ninja' + build_tool_list = ['ninja'] + ALL = 'all' + DEFAULT = 'all' + + def run_gyp(self, gyp_file, *args, **kw): + """ + + Args: + gyp_file (str): + """ + TestGypBase.run_gyp(self, gyp_file, *args, **kw) + + def build(self, gyp_file, target=None, **kw): + arguments = kw.get('arguments', [])[:] + + # Add a -C output/path to the command line. + arguments.append('-C') + arguments.append(os.path.join('out', self.configuration_dirname())) + + if target is None: + target = 'all' + arguments.append(target) + + kw['arguments'] = arguments + return self.run(program=self.build_tool, **kw) + + 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') + elif type == self.SHARED_LIB: + if sys.platform != 'darwin' and sys.platform != 'win32': + result.append('lib') + 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 + + +class TestGypMSVS(TestGypOnMSToolchain): + """ + Subclass for testing the GYP Visual Studio generator. + """ + format = 'msvs' + + u = r'=== Build: 0 succeeded, 0 failed, (\d+) up-to-date, 0 skipped ===' + up_to_date_re = re.compile(u, re.M) + + # Initial None element will indicate to our .initialize_build_tool() + # method below that 'devenv' was not found on %PATH%. + # + # Note: we must use devenv.com to be able to capture build output. + # Directly executing devenv.exe only sends output to BuildLog.htm. + build_tool_list = [None, 'devenv.com'] + + def initialize_build_tool(self): + super(TestGypMSVS, self).initialize_build_tool() + self.build_tool = self.devenv_path + + 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. + """ + if '15.0' in self.build_tool or 'Current' in self.build_tool: + build = '/t' + if target not in (None, self.ALL, self.DEFAULT): + build += ':' + target + if clean: + build += ':Clean' + elif rebuild: + build += ':Rebuild' + elif ':' not in build: + build += ':Build' + arguments = kw.get('arguments', [])[:] + configuration_arg = '/p:Configuration=%s' % self.configuration_dirname() + arguments.extend([gyp_file.replace('.gyp', '.sln'), build, configuration_arg]) + platform = self.configuration_platform() + if platform: + arguments.append('/p:Platform=%s' % platform) + else: + configuration_arg = self.configuration_buildname() + if clean: + build = '/Clean' + elif rebuild: + build = '/Rebuild' + else: + build = '/Build' + arguments = kw.get('arguments', [])[:] + arguments.extend([gyp_file.replace('.gyp', '.sln'), build, configuration_arg]) + # Note: the Visual Studio generator doesn't add an explicit 'all' + # target, so we just treat it the same as the default. + if target not in (None, self.ALL, self.DEFAULT): + arguments.extend(['/Project', target]) + if self.configuration: + arguments.extend(['/ProjectConfig', self.configuration]) + kw['arguments'] = arguments + return self.run(program=self.build_tool, **kw) + def up_to_date(self, gyp_file, target=None, **kw): + r""" + Verifies that a build of the specified Visual Studio target is up to date. + + Beware that VS2010 will behave strangely if you build under + C:\USERS\yourname\AppData\Local. It will cause needless work. The ouptut + will be "1 succeeded and 0 up to date". MSBuild tracing reveals that: + "Project 'C:\Users\...\AppData\Local\...vcxproj' not up to date because + 'C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO 10.0\VC\BIN\1033\CLUI.DLL' + was modified at 02/21/2011 17:03:30, which is newer than '' which was + modified at 01/01/0001 00:00:00. + + The workaround is to specify a workdir when instantiating the test, e.g. + test = TestGyp.TestGyp(workdir='workarea') + """ + result = self.build(gyp_file, target, **kw) + if not result: + stdout = self.stdout() + + m = self.up_to_date_re.search(stdout) + up_to_date = m and int(m.group(1)) > 0 + if not up_to_date: + self.report_not_up_to_date() + self.fail_test() + return result + + def built_file_path(self, name, type=None, **kw): + """ + Returns a path to the specified file name, of the specified type, as built by Visual Studio. + Built files are in a subdirectory that matches the configuration name. The default is 'Default'. + A chdir= keyword argument specifies the source directory relative to which the output subdirectory can be found. + "type" values of STATIC_LIB or SHARED_LIB append the necessary prefixes and suffixes to a platform-independent library base name. + """ + result = [] + chdir = kw.get('chdir') + if chdir: + result.append(chdir) + result.append(self.configuration_dirname()) + if type == self.STATIC_LIB: + result.append('lib') + result.append(self.built_file_basename(name, type, **kw)) + 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. + """ + format = 'xcode' + build_tool_list = ['xcodebuild'] + + phase_script_execution = ("\n" + "PhaseScriptExecution /\\S+/Script-[0-9A-F]+\\.sh\n" + " cd /\\S+\n" + " /bin/sh -c /\\S+/Script-[0-9A-F]+\\.sh\n" + "(make: Nothing to be done for ['`]all'\\.\n)?") + + strip_up_to_date_expressions = [ + # Various actions or rules can run even when the overall build target + # is up to date. Strip those phases' GYP-generated output. + re.compile(phase_script_execution, re.S), + + # The message from distcc_pump can trail the "BUILD SUCCEEDED" + # message, so strip that, too. + re.compile('__________Shutting down distcc-pump include server\n', re.S), + ] + + up_to_date_endings = ( + '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): + """ + Runs an xcodebuild using the .xcodeproj generated from the specified + gyp_file. + """ + # Be sure we're working with a copy of 'arguments' since we modify it. + # The caller may not be expecting it to be modified. + arguments = kw.get('arguments', [])[:] + arguments.extend(['-project', gyp_file.replace('.gyp', '.xcodeproj')]) + if target == self.ALL: + arguments.append('-alltargets',) + elif target not in (None, self.DEFAULT): + arguments.extend(['-target', target]) + if self.configuration: + arguments.extend(['-configuration', self.configuration]) + symroot = kw.get('SYMROOT', '$SRCROOT/build') + if symroot: + arguments.append('SYMROOT='+symroot) + kw['arguments'] = arguments + + # Work around spurious stderr output from Xcode 4, http://crbug.com/181012 + match = kw.pop('match', self.match) + def match_filter_xcode(actual, expected): + if actual: + if not is_List(actual): + actual = actual.split('\n') + if not is_List(expected): + expected = expected.split('\n') + actual = [a for a in actual + if 'No recorder, buildTask: "%s"' % (src, dst) + print(' "%s" -> "%s"' % (src, dst)) - print '}' + print('}') def main(): if len(sys.argv) < 2: - print >>sys.stderr, __doc__ - print >>sys.stderr - print >>sys.stderr, 'usage: %s target1 target2...' % (sys.argv[0]) + print(__doc__, file=sys.stderr) + print(file=sys.stderr) + print('usage: %s target1 target2...' % (sys.argv[0]), file=sys.stderr) return 1 - edges = LoadEdges('dump.json', sys.argv[1:]) + edges = LoadEdges(sys.argv[1:]) WriteGraph(edges) return 0 diff --git a/tools/gyp/tools/pretty_gyp.py b/tools/gyp/tools/pretty_gyp.py index d5736bbd4a6009..d32e70f3b2d517 100755 --- a/tools/gyp/tools/pretty_gyp.py +++ b/tools/gyp/tools/pretty_gyp.py @@ -6,6 +6,8 @@ """Pretty-prints the contents of a GYP file.""" +from __future__ import print_function + import sys import re @@ -116,7 +118,6 @@ def prettyprint_input(lines): """Does the main work of indenting the input based on the brace counts.""" indent = 0 basic_offset = 2 - last_line = "" for line in lines: line = line.strip('\r\n\t ') # Otherwise doesn't strip \r on Unix. if len(line) > 0: @@ -125,16 +126,15 @@ def prettyprint_input(lines): (brace_diff, after) = count_braces(line) if brace_diff != 0: if after: - print " " * (basic_offset * indent) + line + print(" " * (basic_offset * indent) + line) indent += brace_diff else: indent += brace_diff - print " " * (basic_offset * indent) + line + print(" " * (basic_offset * indent) + line) else: - print " " * (basic_offset * indent) + line + print(" " * (basic_offset * indent) + line) else: - print "" - last_line = line + print("") def main(): diff --git a/tools/gyp/tools/pretty_sln.py b/tools/gyp/tools/pretty_sln.py index ca8cf4ad3fb836..e981fca8f3ea0a 100755 --- a/tools/gyp/tools/pretty_sln.py +++ b/tools/gyp/tools/pretty_sln.py @@ -12,12 +12,14 @@ Then it outputs a possible build order. """ +from __future__ import print_function + __author__ = 'nsylvain (Nicolas Sylvain)' import os import re import sys -import pretty_vcproj +from . import pretty_vcproj def BuildProject(project, built, projects, deps): # if all dependencies are done, we can build it, otherwise we try to build the @@ -26,7 +28,7 @@ def BuildProject(project, built, projects, deps): for dep in deps[project]: if dep not in built: BuildProject(dep, built, projects, deps) - print project + print(project) built.append(project) def ParseSolution(solution_file): @@ -100,44 +102,44 @@ def ParseSolution(solution_file): return (projects, dependencies) def PrintDependencies(projects, deps): - print "---------------------------------------" - print "Dependencies for all projects" - print "---------------------------------------" - print "-- --" + print("---------------------------------------") + print("Dependencies for all projects") + print("---------------------------------------") + print("-- --") for (project, dep_list) in sorted(deps.items()): - print "Project : %s" % project - print "Path : %s" % projects[project][0] + print("Project : %s" % project) + print("Path : %s" % projects[project][0]) if dep_list: for dep in dep_list: - print " - %s" % dep - print "" + print(" - %s" % dep) + print("") - print "-- --" + print("-- --") def PrintBuildOrder(projects, deps): - print "---------------------------------------" - print "Build order " - print "---------------------------------------" - print "-- --" + print("---------------------------------------") + print("Build order ") + print("---------------------------------------") + print("-- --") built = [] for (project, _) in sorted(deps.items()): if project not in built: BuildProject(project, built, projects, deps) - print "-- --" + print("-- --") def PrintVCProj(projects): for project in projects: - print "-------------------------------------" - print "-------------------------------------" - print project - print project - print project - print "-------------------------------------" - print "-------------------------------------" + print("-------------------------------------") + print("-------------------------------------") + print(project) + print(project) + print(project) + print("-------------------------------------") + print("-------------------------------------") project_path = os.path.abspath(os.path.join(os.path.dirname(sys.argv[1]), projects[project][2])) @@ -153,7 +155,7 @@ def PrintVCProj(projects): def main(): # check if we have exactly 1 parameter. if len(sys.argv) < 2: - print 'Usage: %s "c:\\path\\to\\project.sln"' % sys.argv[0] + print('Usage: %s "c:\\path\\to\\project.sln"' % sys.argv[0]) return 1 (projects, deps) = ParseSolution(sys.argv[1]) diff --git a/tools/gyp/tools/pretty_vcproj.py b/tools/gyp/tools/pretty_vcproj.py index 6099bd7cc4d8cc..3d5262065babc5 100755 --- a/tools/gyp/tools/pretty_vcproj.py +++ b/tools/gyp/tools/pretty_vcproj.py @@ -12,56 +12,46 @@ It outputs the resulting xml to stdout. """ +from __future__ import print_function + __author__ = 'nsylvain (Nicolas Sylvain)' import os import sys -from xml.dom.minidom import parse -from xml.dom.minidom import Node - -REPLACEMENTS = dict() -ARGUMENTS = None - - -class CmpTuple(object): - """Compare function between 2 tuple.""" - def __call__(self, x, y): - return cmp(x[0], y[0]) +from xml.dom.minidom import parse, Node -class CmpNode(object): - """Compare function between 2 xml nodes.""" +REPLACEMENTS = {} +ARGUMENTS = None - def __call__(self, x, y): - def get_string(node): - node_string = "node" - node_string += node.nodeName - if node.nodeValue: - node_string += node.nodeValue - if node.attributes: - # We first sort by name, if present. - node_string += node.getAttribute("Name") +def get_node_string(node): + node_string = "node" + node_string += node.nodeName + if node.nodeValue: + node_string += node.nodeValue - all_nodes = [] - for (name, value) in node.attributes.items(): - all_nodes.append((name, value)) + if node.attributes: + # We first sort by name, if present. + node_string += node.getAttribute("Name") - all_nodes.sort(CmpTuple()) - for (name, value) in all_nodes: - node_string += name - node_string += value + all_nodes = [] + for (name, value) in node.attributes.items(): + all_nodes.append((name, value)) - return node_string + all_nodes.sort(key=lambda x: x[0]) + for (name, value) in all_nodes: + node_string += name + node_string += value - return cmp(get_string(x), get_string(y)) + return node_string def PrettyPrintNode(node, indent=0): if node.nodeType == Node.TEXT_NODE: if node.data.strip(): - print '%s%s' % (' '*indent, node.data.strip()) + print('%s%s' % (' '*indent, node.data.strip())) return if node.childNodes: @@ -73,23 +63,23 @@ def PrettyPrintNode(node, indent=0): # Print the main tag if attr_count == 0: - print '%s<%s>' % (' '*indent, node.nodeName) + print('%s<%s>' % (' '*indent, node.nodeName)) else: - print '%s<%s' % (' '*indent, node.nodeName) + print('%s<%s' % (' '*indent, node.nodeName)) all_attributes = [] for (name, value) in node.attributes.items(): all_attributes.append((name, value)) - all_attributes.sort(CmpTuple()) + all_attributes.sort(key=(lambda attr: attr[0])) for (name, value) in all_attributes: - print '%s %s="%s"' % (' '*indent, name, value) - print '%s>' % (' '*indent) + print('%s %s="%s"' % (' '*indent, name, value)) + print('%s>' % (' '*indent)) if node.nodeValue: - print '%s %s' % (' '*indent, node.nodeValue) + print('%s %s' % (' '*indent, node.nodeValue)) for sub_node in node.childNodes: PrettyPrintNode(sub_node, indent=indent+2) - print '%s' % (' '*indent, node.nodeName) + print('%s' % (' '*indent, node.nodeName)) def FlattenFilter(node): @@ -186,7 +176,7 @@ def CleanupVcproj(node): # Sort the list. - node_array.sort(CmpNode()) + node_array.sort(key=get_node_string) # Insert the nodes in the correct order. for new_node in node_array: @@ -200,7 +190,7 @@ def CleanupVcproj(node): node.appendChild(new_node) -def GetConfiguationNodes(vcproj): +def GetConfigurationNodes(vcproj): #TODO(nsylvain): Find a better way to navigate the xml. nodes = [] for node in vcproj.childNodes: @@ -283,8 +273,8 @@ def main(argv): # check if we have exactly 1 parameter. if len(argv) < 2: - print ('Usage: %s "c:\\path\\to\\vcproj.vcproj" [key1=value1] ' - '[key2=value2]' % argv[0]) + print('Usage: %s "c:\\path\\to\\vcproj.vcproj" [key1=value1] ' + '[key2=value2]' % argv[0]) return 1 # Parse the keys @@ -297,7 +287,7 @@ def main(argv): # First thing we need to do is find the Configuration Node and merge them # with the vsprops they include. - for configuration_node in GetConfiguationNodes(dom.documentElement): + for configuration_node in GetConfigurationNodes(dom.documentElement): # Get the property sheets associated with this configuration. vsprops = configuration_node.getAttribute('InheritedPropertySheets') @@ -320,7 +310,6 @@ def main(argv): # Finally, we use the prett xml function to print the vcproj back to the # user. - #print dom.toprettyxml(newl="\n") PrettyPrintNode(dom.documentElement) return 0 diff --git a/tools/gyp/tools/vssetup.powershell/LICENSE.txt b/tools/gyp/tools/vssetup.powershell/LICENSE.txt new file mode 100644 index 00000000000000..d4edbaef7f6b9e --- /dev/null +++ b/tools/gyp/tools/vssetup.powershell/LICENSE.txt @@ -0,0 +1,8 @@ +The MIT License (MIT) +Copyright (C) Microsoft Corporation. All rights reserved. + +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. \ No newline at end of file diff --git a/tools/gyp/tools/vssetup.powershell/Microsoft.VisualStudio.Setup.PowerShell.dll b/tools/gyp/tools/vssetup.powershell/Microsoft.VisualStudio.Setup.PowerShell.dll new file mode 100644 index 0000000000000000000000000000000000000000..2aeabb3bccad275a1db107a5bb036612701e172c GIT binary patch literal 39424 zcmeHw34B!L)%Uq~X6`JR49R3;$ud9!LpHOK1jR@;B+4cUh>CucY>-SGRLbMKv*kYHQu_xpX{_xlF! zxzAai^PJ~A=UMJ^pP4K>`x>$lksa4Z9}zu?Hr(pP78 zY>C7I{ZV~$G}IgD3ib8r1A&dfPb;)KpKQsd{BA(Ne`mpS|*` zwN`0|X;vUbsUW%r6qi9QzaRGiu7kLU(j=`Kb~AzPH$Dmx==`zKqDxtn|0nJy$|QW= zx{qiDCk_&|I5=_4=P;2Mq`U4V$~}hlv1lM}x`?@eFGz`WI~_n)1V zS#Jb;tw~Pg)lq%V+Tx4~CtZ%R;iB}+C@koodQ}!oDatmA_V~%K9L@5bD)ungWLVN`}bFw^YB)#LcWsG_nR;xGL}$ zdV<^+^F84=Cc|$+P52Fc7JfruC;N>>HPJKPZ=6>fW|;8Xe@z*&N*`vQ3OP&O2$mJv7d5ocj~{jZ64f{MLs2?6=eSo`^Rl!*4=O_{|}H^N;r%i)zCR z$NP=*YN9vcw`D(ixn-Q+B-=#4ao$P&mZBv0Q_lSf{l+Ey3x1RF3}c9$5c517r>oH+ z*cQYt7fKud9IBe1~k9A-Go+~{tu zE%KG9NmTtBNRQ-mZuLTpOZMn(5K9s$I_ku{rNz!+gU}62AeYW^Pfd`!{#ZH0ojv-K zxZF|gL6%s@nh=<*DT5`Ps#W4q4c$zOoy!tvB9_QxiGsLKNR63%y2d;D0#vYFXzFrPSCe9i_sw73-x!FRXX9nxJC$7ix;+|t`hP9GC`t$_3J6UcEm+Cd@m&bD7 zpCEU~I5}rh7!AMzbp)Nmj_Bi?em7)yqF>pI%5vtIq5oCRA3-@qqs$4WqO_gpbjdOg zu*_DGVGf%2>rClk>&{|;>AhrRCRjX5a%A(JL!0j$x_sx* zTJa}uyH{Z!oL>pc{$AV7s8A(7JZQV<>2~UmMcJ(}1_J;Ch%eRi&fJO7(xKSn(UR$T z$1w+hG>H$yCdWta0&*ZJpWFs=fTwISV!{@^5oHC@8A`C^ALQy*sl$BNwdswA1TO(7_42f;*Da#kj51$@il^@^H^O36?rVappdmWNLH)weFNb)sNu4_>^~~{9 z9s|&q(Fz#Au?C5O9mJ?pVvCM(5(7_(J$gMSbC7ftm1%Q=yHQG-4fbOgDsjZF0P3;p zpTRAqB-5#1iG){k=~v-iX3tK2C)=q*(o^={J054L=G39d^Hxr=yO_rc6_1mFjf4<0 z)`=asd&QPJxKzwYu;m_3u0&l`{c2>k6%^>7#XUG3Ts-m>Y5KK52e}POy#}(Mkzykq z#JE^eEZwP^{Wl9?B?x=TWvAydL^z1aAN=-l+yp1Z$)U zIn`l?WhrX#Opt;%GM{~Fr>O|?RIZ01;Z*gTm>GTh7KaE1~;&hTR`!;q?ORQO7z=+r2d!`5^MH=#BF*Q*(tny!f@e{W6*u0fu3M{o~o za;oW0amG93mKvOR!ABo`^p3|}s=19C6e}3uR4S*u(~Y)Q=w8bI51RHeDyq^hx*}DP zn3$zzil>Wt`uY~i!1T4A+YE9Uh+RMKKKR*I>a)dAHO-@H!M!kod+QhYZpdM(G~@jTJ_;w(+IJN3JeFNXPqGv99$ zbP!{@%9Ceii6i(Ln_QMM=QZ>yMb_6krWOy@{uqZ*P8ye^W1jF>g>~BWF9S_+?wk+9 zW(4mBQtE;Q5Z8(`y-9_ny31^tC7L_UV&BNH62mh*EjDmo?#Ge<;S`G?2@n=p1WAChvAc=QRW0^LQFlXVN%gzkANJU1;S2! ze5QAq`>14MP7s4)3Cg>`ERXN;@(^Ch<-NyQzb09k6D%~!!?dLFL!BpxC@<&ghFZZd@Kk|Kq16>V1%d)rH^yk>5 zTqA@GOqV6zS)d0?QP<)e*>6~cR^X3Ke}Qw<8uy*spiCZpj9~j2JL^RV6pb>+h!~@z zV$dkTrs+nT5$QJlTM*-ES&O}dRPhz+Fh{*je;L?(zj0TGxepw*Wgk_Lw>*ZiNEwyM80YCZpfPbS#KhLdd3n#l+YO z6T2Y3+ujbM%5#fH{~o}|YT(822+tkYp<$4M^xp+b*dtlvsN-2h@s%>NYx|g zL#!*CX9vzL{#OaH$Zc%eS#Y#EPaWoZB&t=N0&~P>Pl+>I9+A17&V@m}xmq^+G1~vSwp{a(!gw zCjLZ+R^c0)!T?g9+zpy*Wy&Xf|LlSe#x z^mrY2b2R>C@@S0MHJ&;0XnLKo?o6~-n6)OVF|wI0k@8Vr9)r+cEaTA%{#I_+rd50B z9j6-n5iEGi(wmMYGjF}J-46PqLX;oRm*Q--gTdTJTo2DiR`bV^vXw4#^q~#3%zD@;Y=#DNZ#E z!@QyC-$z*^JuF=CH&Ix!Q5|Mn{{c7|4#OtDBltt0))Jblbj%W(&Be0`1mS*9da`e( znTEboW|d)2L8p!3#3)ZIg%I09`g6y71I$x5}m;23>~*Je5&X`)N&z?A#ddhqu?1SCm&*R97wl6YqTC4Z3$8(d?a=7m#5~ z5z_4g(MaEB^je}(1oKijbN1?XdIiI38fddmUES7#`&+;>vw=7D=;-$HQ4#xRp7Mnh z_Y|OiR;qdOMRO3GL8v7S;(8y~6}Zp{1UqGpeiC;S&27NXdvqeM#kkN9<<2^|jrpE} zi|s&Y;?tJNG*p*Lrp(IKXjK}+!vY(9Kb?_5-$8t6bcgTGY>oCzVK^r6#WYUu5_qq` zpNLF>?_y}!?Xv+sm&))>(cB=p&Jp-$Uy)y(7psP*agC1TTnwF>FFW5y zEvY$~KI-@7K<9rWmxl_V(@!TBq-Fc*&p8ZlPfLTm%lmSspT6y5%Kr%W)oGlb39g@N z1pW#Xl!dzZsi26{D{P$pGvs~rVgCL3emW|WPfcO&yD99|hsDG0G)_0CaqSLeGK>o4 zk5ZQ{ex{r`jo~Q*KO=tlDDTc}53TnsoT||yLcdJ>`9L;ndmqq8XSul*oKDVr(+q}B zWi$MX!1NqWKR)|T)Z$wT*X5wV@8xm&SK@&Wkk)89B>nWA8BBj(;JK-seiUhqKAM(^ zNcfGkSFyB9K!Z3w(;N(?_hI__ExN|)IHuVcv++0uUanvc-gyF6C76@fE5II^&5~}c zhDL$y%P*L^8oM0Rr6=6uHn3db{b2@Uv#0{RGbF=aoJHsq*FmpAXKx;*3v3oG{cfigT?CoiTnTj%>Fis-h2L*#z&DT>* zc$tt)SL$gy?L}7&<(6R_Xr|qQt<5&DD+JqTOUCw2Gq9_Lcaz(|t`Y2dQ_{e`WAgS2 zZ=u(ayqox~ML}v=cBRrx_XzJSDep93wwY;!4N~}1F!-epwy#Fb50DMmI^DaWMDm?YF9=p6*g5nqv}hVNVjx>hA$m=CON7@&ZwPjhln|!x zC)v_VhiN8NIe!g!rStdk^tPmQtE9am(}{HZ=!aRa+S*4~35*FmH-#xZ*$hv2ziO+b zrFmz1W|9~5nRI6c!|XN1^$y&jA*= zZueBud9c5ddS)~Cb9s9_?W3KjOZ({I{JS7?|FpXS_q*={ye8`a;QIpKbUuvqH=#kn z_5j1vT&&>-(5z|wj>l1#S5h_s{yu}@>l(wK2+S(r^k?C{TKc{HNl!LCW67^w*elqj{#0qu1Q%L zK#OEUZC3i{V6v3riuO0eYIkz4^3>TzYf^t zGYKC0~4KgdO$Ekr$&D?G1lp%(pjwK1!A2}Iw+W-(@Eblv4*T# zr;}bYFwyCxUzqvWPB)!^F_^WmP7igP80+-V{|I)O>uoCKN0UO9yv$|Ku626IWniMy zLjl1IJH52o#8_u4-ELy6GnFcMDMVw)r(jN~7wjfd{a;B*r7KPBZtsBR|g=3rgNw!G%3!`N1CV()qwt2ME~48|Hv?6$0fDQUFW#D3&`9@ugd z%SwG2*cub7O5uF#O>A}!W1CFu8PVBiV&@lp2l=*}*gLte1KVk0C+EEl>@pKOin^!K z)h4zxHGr}7CKEfw!`PjI?Q-=?zAp-PEgtfI4lR!fHby@y_W^Nk{Q6>(^)3=E72Je%!sor z8W7B|C5wI_*iGb1b$O@Kl2Wk+mOZ3SrHz99++8~RYGoSfCYE1twQU+*Xkth5ZU(kn zup{o`!T{C+SDL*2nO^|!Ruj8Fb1PN`26jZ5tEGB#UjZvI`vbS8f|be1!n@uz zIIYE7MiCR+>RqLlQNM|u?>!B?9VXW4Kf_y2SDV;cm9e`_>{X4iCk4BSPR?8nY)Lt{ z(M@zx`VMaueOa)}TxFS;c<0jtCN@9w3Sf_$*a!Y=y|whTiT%O<2-VWdCf1yBt+$T8 zYhvvgk5C=`SgCe&0ZpPMC7?>`+uwY{}n0u4Ao_3hn zgguIE)y>;pgn@UK)dtyco)zsCbp{RUhj$I!ZRk1XODRv_AaCv6FVvW>)w;i zID3HxJ=mC>A3hWfK-4W&KFL@Wy!@?V*&b&k3Ci<0$?auqYx0(KCVn6l2=WU^U zZ1rFy63bd?j$lR+Hyfy=)M+<)GZKZPsdyc-A`LK5}^&31_r~7x_Q)!2Z^|=2C zY|O;YFSypbgm#zREQD9bd0)*~k($7oAbDn-w<&9N>e@Iq&2x6@S#j(q7~R&zv0r+-Qn70&pBEhe zgPCM~9J>OeerFte2>#p<$C^?isi8PlofApzieq&diX$Ay&ciIj&lCK4!9jU_sap&L z*uH{+)JPorF3K}7tG4IGdCi^xC9sQA1GF{H+nqO*+7ri8p(TM$(dv}mIPV?Qp)Zd4 zF+b>nS>^S|d0)b8k-$F0Y_ToQ`!hTkjbkZU0X!iYpBEfo$h+1%5XY+0ccu>0b_IG>i9m>2Khcf@%vMR5#`({cf=GbNv(gDDr# zC9@JK)*t*wkHgk^Qr&7tmA_yVw3Uc*cswu=4`C*yO#Z zvX)y-?2k6a9yGD*)Sb|hobN(9X!24WJ5w*De;15(I%p^TO0Xl!qh5tBqTia>(%AuE zSJ$&;N8BgO`cBG4@!3fUu%yNNa8@O-n+-{2&-9y9FQUUH#L2Sz? z)eCl+>rjf{HA;(2>_;i@fY)YXj-mspV|0dz`HQ{=EZLtIAA_wE$z2%tzma+|J!#|< z?_NxA31)bA7iFGg*upj1Mei+SY>X~Z6<~C-@Z8tVdNy^}xcVh{T)$o9G9(rIjF%v} z(!{uayJ)RoMwIUwXXh^J7Tzw}N3SE_4io#PdL;D{8a1)QwqK`SN;jC;N%oIYFQeN{ zY>VCD`!~AF#BQ`_`!1*FOzg+@S-#!$x{1wJ%6wO#I{f^F?Qyyu+m8yJo1UQj278C& zDNR`k$`RyM@tm8WB&S)Yp;@8zSedIdlEU9i`kcuBT(}eIUn=BWcj2kRfU0TF^O?t| zD0C_0RSHS2gd}TFK{sj?LG4ufp@;P_<#=g4MT$4>!wVD}%`Hevv(t0aIG3SeBqc4) zCQo^mXAJ!bzbUjzJju|gHJ)nWf#X5T!eoybY4(^xMvan7nV2@@xkVI8h6`0Cpiosn z4X9KHXrqG~1t3NSWbUsr5@}a9Q*hh@^4Das{QFtS^2bZ3S15SiH@L^9=a~ABm-my= z+0HA(KO990T`%bblscO9dHlMQ&%Sc|IzyOADT`*CTwZozd2o)PkK?Z-78*Dbj2z_Y;|T>Ej&!gUL-JFw@; z>-}^<2Xu0JCZLBZ0n-R8T);+wZ352_c$UDBz=*(YfLSyo=`n%31zs!g7J+*K6?zrGG0706wX$ zL%p8FGgmGxn5F>UnjZuFQO*$HU*t)N;Wp&DhK8i9YbCuG@Fsdm(mw>egKDJQg;Lh< zKvC#VfR9j%(3c9mQf2xAz%*(D{63u_l(PhK`WlJ=zC-I|r*WO^G~O*W?WU6hZlxQ0 zG8tG4ak@v+-PrG#jWol%Wd~(QtuAO#E)flv5bsZ3Dd{VT_a|>4-k-dIcz^OG@?c-% zCHi$H!zt4lP7}Ci#&yb&`jf)XD~C{e8XY2~;4Wpix*>2kC@BT^D~FUjJP!lz&U;F^ z9WsZMy=s5K_m#WV>%D(c?gB+q?-lyP0-qH4oWR}68axN?R%SV_R$dXx>jL+xHx*u> zzJ>Hv>U%=@0PrF81KE50P$+*DxL5Ui-%{=H@FB%3aIbo6p=Qfe>OH0Ov}*HQ4g0GL zT5K<=&!n7gI|Q$y7D|a@gYAdvkUL^4RCp&dm-v|;v5sf?LgHt5#5|tXk4TFY5T!Rw7Jo`=C7$n~U zT(t_qcL$Uc0?RdCb4rzE^Dv4BDsJiqb1-rY)9p zx&4TehgIv4TAP1^eWrSfKaFOpSK;~Ph|)6cDSM@Df9A9H1-8cvUP9iF3V&c%=Nc)P&61l}v~VS!Hyd`{pi0$&&SmelJ#sn`3;oIt+w2>mp($T?F= z{6OJ7O~ga~NzM-y-i!RJCA=vBhH8|OM3zEONiJWg~yG%=|imgrYU~~EL6E2OI2>i8nr0B)>)%ogY*X| zcPk+8xPB<<4<&6kZQ$KVyUJW2#-UX%AKt!(0842HU0$xd{ zxP5rv(E@moP6vFBI^1~cMYHgQyF-9JysOv>$@eJF? zz(VCDj|+R$vjDFJ^wTYXGqJAAPA|t>+_|1|yyH6LE62%{9|6v$KLM7II;EVdsSNNW ziU2l~4tP3U0oYFa0M8M67yT6Jt&)z>uaF+5oV0SRF53V`L7YW=Ta8%$f<-e#P z{aNKCWgcKNy!5QXHXIi2y9#@NRL*Nt&r!}xx2avq-t>S_776SE{k8Niq3=>T?=Ce) zAEfV6?@_Y-yVQrEbB{>w6Yf563;g?pyHB_Wh5M{^P*rnVE zIIQf?+#}qVkp5HV`+##j?>lY-bZeY;Yn%>ftaF}F=4tzs6SCSQ9TNJOz^9!ob3~xx z;`B^`jRFIn)0H2mQ3`uFAaGF%%WM!hDsYd$nO>$h3OwlJ^kIQCh0_6niv+ezd5ASg zdQ{*gLfIqfg8~l=+>^$64+=aikkW;c!*Oz0U|=ez7YW=Ta8%$Pfi#V|0f8F?jtbl( z@SwoM0%^L~DR7a%4FV5OXALxi;Rb=D0`~|!DDbereYD84pPD>h!u@V)_1uH&K04L& zRooBY{tzzg0D8WL>v1~W^L1M0c?$P$;(8j_v$&o|-WPFy3HNW~{wnf(2kAq!!t*`g zZ_p~w_i_CY=^x{I8`n>89l`Z3uAkxh5Affo4$prg?|;)gQFH zl*Q>I#4@gIPXE-g1n@5&hF4`Ud^Bq*;IF)A0QRP?0c=fSdTkEFH$>)(1?M1b%i92W zWnKg@P3RY=Mv-pzFdPuNU*lYV6`fgAIsFwsLzkDKFN-DrCN@;e-j4LFf(rnDmUju@ zGqag{F!O4_p=mb)e#UznV3&U{;5wDzA&p^c=6=9mWZVN75x6;n^WNir0Pu?iOb>b) z{xyrsZJo{XZw0s(x6FJLa9aSsaAKxi-ftqky6Abp6K8(gq#JF*&)5!JPW;1u0NO>x zd%F}sAMPqzWeQ*>o@G=#`(ywX;0=lFYNfurKNXg1(n zU@GSDxq$QVPeof}ro>eSSc)?lDpHkzm1upHs?h!_QgwhehyfM&Nr1K3zQJ=aodUQJ zPfsfFX21q~V^9V4RKP{p7gxY*LwXhFT@|zLGEh1IRXHD_;`O+0jl(4?6a!$Hcp&*q30C9 zOHd~-U55I4vEFF~yaM(0($%P`7bl}n2fP7w^y0@;PC|R^R89aKRVo25R;mFn!D*LS zbeU2Ic)79w@CxN5wAOWyETkJCSx7f2=K$Ue$wImnl7)1;axUPVkeo{oKyofU2+6th zsL}=a7$oP?6Of!sPby)+Z-~zMuw)~4-S*Rc^mVMmUZtPmY|9L#2J49>$~vWAc~SXD zDN-xcdbL$utA^Ff)X%B+sxPUptN*PYRTtPAZNs)_Z2|iU_B#71_VxC6?H|~)9cMV! zJN7%CalGaDlOtbSq=mIn?Pl#o?S0MX%yyPJS31vi_BaQeW6t}WQ(Z-_DwlnfpZk+P zgV>9*ClMC8b~qRvPpj}wq`i!sysMP>w7Jr-A7*^Gl~b}HkViQ|Nx;4Tw)(M5uLXo<+eY8qk3037F!kW(xcr>uc{NdQ^NyoeX)U1 zAGi(OAR})>S7&ESB-Y;(8fxwd#bT8eouVKm=C7*b3Sl9_U=yu%)xJBO2<9^@pP2zJa!GfXJpuILhXjb+0_8?!cMF z)kSi$@|g}dB$Wt1fY`ZaU}Mjzq5jHF)^V&);O66~qlMvy`OuJT2rVA$>)KFBZLNKS zz2RtRV^5f|X1%8;+%*u<`+%(qhq_nv^$e|SUl#7&7>>5}ZPF(d7)NYt-8LBNi3|)i z>%HujXi_O~Dr4>80o;~^Vq1(<+tNskDGM9wIy=vgqJ~Hw&$X4}`sKP6C5!dw%Fw`; z&c^8GSS2;L7cOk5@9e~nRfT$hFKp=T>|7k_3-$C2jdMWNq%LHt(Ktv=);1t-3J-K` z33szgfyLvRvu^6_Z0ytfhI;kESjSL*xMIU()XGVzRg+SyL6xSeqSM1e;qD|?3uR5H zXE3}n6p2EvttBE&7m5x6vs!N)kzGI7Z@CUx1aH>+HbpiMMnl~2Y_Zu4NOBy8y0(Tk z8@+LUb=*NnP39nw<1S%gQ`K>#Ym%gqHhn*Ta@8QmRU>T**G?`Ba$Fc`Q@Cz&VUXj( zNV718t@b=cN+d*jU zT)v`X@ru>UTWE3H($&O?dN7G-mexEN<>As${4o}mCyhr7&6-Y9k#h8mct2R! z0j#t`@P>x+#_sNqEg;c5#$}Xz{axXnfyG8|HwT@8RpHGTtHRN6H!as!g*WOtNZSS@ zOfV*jHp6R?3qa}Vioj2U01J;lpj9+Pc!&!3Kq_KReUp&ZgrhNZ&m_+F2^1@Pyvt71 zjKJ+4>>5Z?)7IUvwX?Gcy&PZ2FzrY*?D2UMIUK?hsiuD>GI-dYNNw!tnMkxMKf%y= zO(${^6ZQliq5`3HMiW$lV($=?K-)hz`wlsu=$`)RqP$U^iTDb7U7wgw!BGeW``2%JW zvzw7zHHd{-ZNr*0w%W zU=spT2=JZUrFy0bLKxtDXKq2zh#GTH5KUG(KEgxB3^r3kI~I;8RUm6NCy>=`&4WDy zSe%PWE6rWON=L&+P+B-=UJ>o)^?5Pl#;c5fC-WVJ;=aX!W#!SZw^PBqWbv~$p*O<1C@R( zk!#V8hbIJ_A%*gd#KMNk&d!*qXQ8$jFT#5eV(2{aWXll3Akx)1fUn?f9AwiVgm{R` z!T_dqCs;grC1JdBU;*yV39@B7f@F0pEPXw}Y#;3JM>E8h;X>z6FqVf02cn^#Rb~^R zbN6i?94BGu<-VNAWtA28Q-XDjuM!N@Z%rf?8K=kUKOK>QWcA~sIiX?2;6VSNM0SD} z*ANYLhkHZOtqE2~C<^y4=H7k2p3JbUUlQrYvtlAc>yCkNAGc?MWU1$#YL1l?nfyo= z?UkV?)N@>^aqIhuN?O9Pu4ts6$FBs_idzgU=-){U@euk?%yemop2*Y^-V{QQG#(cd zWF7z#&&COQeEdt08haw4SOQ(#6WW}F8i6X+T@~&L?U2+szU&Vq@>@>C(8#Nv1f#hZ zlRy$~2{!BfLs1Nfld|wU+c%WZVNNP+6b#uI;fLM?*K*);%-onbRzzES`;+;`5>>_n zS*-Htf_`kIk+4Q{gMb-gJYhR8_CI!Mn^-A-!nO0NaIe1o`2L0A^T13r^i_woGEvpvj;w@13eveUrRr!nEOjG1D6 zJO|5!CJCmr_Q41|o`Vk2BrKd@@Z8M7JP_G#Nb-P)GUG~?V)ce`GOj%t=R(?I6DYiX zGZ!0H;pY4#Jw|BeB$Xh*LTgGg_f(|SP<8G)mY!s^KZ(`Pm0ZfZE>@E!;xAUdV&i#O z_TsTOoW$hokLV!aY6Z-T$~O7Btc=rHXBMgqDIO0YBgo5-t!7&hIsAga^FAUaWVGB?TUt zN$>Amig@eTf;3lPRd_q*8T?u%BWW%bSip0L8D6!~l=OkpY!wje-Q7hRS+F>Ov11y{i+HO3jT5)0QHT0t8 z%Nqv=bYu4V_%b`n%}JUEN>!M-Faw{sLzVnPm^k=R!4lMtIoO;Ff9Nz*UKNiy15K zcC)nuCp!H;I8@nBeE? zA>nZ?o3}*zxq5Q%V&vm`wPik@J+^)P-pP5`fyX)`Y3pPH#dK6doM8rJf?)Nt_-;a6 zG|n-%O)N(IS;g8fk8i7e8t&~0qejhJ0N8cL^DsOrQxLUbXhNrn<3?b}_CnamU@fVQ zo))#7$&2(0MM2hh$XXKaK~oV%P`)LH8PG0s6QA18k6>1euh`;GFOA)yeuQ39 zlUtOfp$pLbvW18hfMMCP(0RI zc0Mr)%lnQ`tH5KoLq1^{W;jhcG?uSyH(biA5b0F^Kp{!nBgfRb5yRj15Z7OJqyhOg z8m1l|29e;29&3F3I!i3lg~ME!|BS`56>v#R)9jW=2oKY-0hV7b3z=o%fh~G>%xY6> zbtlgbdVhO3x;=u0+OcdaFynk~EGz)pcuL|If-(aqFsY=h0unSdaRM>zv-(5qW5=9w z)4h1bS02xSzk6a#_c1b_-LSUgWlT(ZrZrv&5;3ie6Jbg`-EY1``A01<)En&$gHU)^ z4_>BOA;6?#-%CoC$#yn**iF=p`V(5g;BBD^4RK66@rc3CaIyF(Z(y4-ILYHljI4+E zmC;Bqy8L#?Hbwfd(Xv?{;qXGCrn7SZf4;|R^Q4%8dh8}({v3*dFRu^dV*k75FJo~@ z@fBLUz>e^a0W|;SLAbkhhwNNnK^JEy*)wheULmW77~Z;V4)3rK_79KZIP@4#E!Sl~ z)QBIfGh?)s0S2zF&;S`jJKSt6n59XZutjB}8xu)+Ix@++tggw}Tec#H7wu9mnqJau zO*}?T8Uny#BP>MBcnqbaXNvfskFG}Oj^l8MGZ|WBXp(fhF<@9to#eA}Yh1!e!<`H{ zv4(EL9#y0(GC=&og|Kx3$kv+M3A8v8jSZ}bT4=Yi%YbLX)%_?G(_<(a3H1$3R$hF~ zlNk5^r5VKBdHht0G6#qFR(eDEKdJqnoi#p2eR8{ejM%5`PU#`W+ra-#F8u^0{IhQT zJ4GbBHd%CGLse&ImsxpX;Hkn0eB%X^^jFtWG!vY@hHJsQJ8~k(nLOFP2)p2 zXLaT<&NT*bYOxRJ5fK)+ci}u^0Ou|P;8ftGW9cOPl@!H^#%`Qm>_RR}x)Ra>Tq8th zeNw$4Xxs`rHp2@3oe#r~B+Z}D;x*8Rr7CKwqmGm4?KLc3h_j|!aKf$=ry`=_j~ISY zJ%n@^`37(nv)fEXXcM%t){3}3%U|37UTIUtOHlf;EkHBd;%(A{-$4waY{T~DNcTej z@g-J@G=7<2?(uYt_Xg#Rmur#yC?Ta?Vq$mC<+@>kx>6Ff#xb<+Ah+cJ>K4F>P9yebA&tE{Py=XfUG#M$ZNw1U zGQQVvK91E{IOk3o95b6lE5{D^E1GhQ=iSY)j{QcdO(@;ye`q;(2kc;rxNWeq#d&0| z8JA~70i~}77NKph2`>Z@l{E5c)~$bBs{~-%v2`)L6t8VtCC+Wv;ny%L&>l57%gpD! zo2dn-yvu;&ToSltpjT5B=w-kvL2Z(M3y_aFwV)_j-KZCjD@IMZ?_sFwS|(I(sTi(J z;Fsf^H^<~4Y{lj=R(Fklav{d3}dRcxzO5lj)7~$B$D|57Sa+&z`VNf|T zxxTEA+*^SSu{EhWqV_zKN7Igt(nJqjiZYB6*bkOP;VN|b#* zO2SqO>cSTFz;E2I*y?p?od_s+p(B=YS-tqJM*Jv)+b9{oO42@=-s88A(I(amQjX~0 z(UmRWda}0_V@eiqoOGs{1^SMdk!0UQ+vA(shbAh_`xUd+lM zM}YjJcldxEP_oiTA5k+1KS={M8RW|H4+-iFs6d4boUuG`InP*f9#!%AG`3~*RVQwF z{?YeM1G>#}yIFCb4~p5WF*he*&Y0VsyfsaPcF z9K#pU@pTi_MN+Vgg~{Y_HC!3^QEfXDGn5PkTzJ8!W+-m5p|nO{UM`C8N)e*kNP?D@ zpczTfG7~f-X~$ntaM?YIKMb`lXTYww@Uc4;f5c9T%FSVOA!V~U;53)bMO>-$u{L*r z-E&p?*fP|7bhnDMk418)PES)+@k%}_3g_f=L+w`cDPO^_h>INl4#(JP4dfpxK73)) zkjr4XH{cGZQ}tiyA01`0x>@Q{#b@&qtBaiLCzmc zkxW_sL8M(Cl*EaYGz1wKY#a(0k$6&snL$>LA=Q^FIXD5S3fxlAs8&q5g~rWd*obeI zD-y4}Ri8R7Ena|G4sPrOOG0V`$=uR3n;orxmYT2RTQ-@p;z02nGu}}06^F;>^GP4L z6sAL+hA8mm=AwlZp98HndL`F-3pe0etF0m$DY*0 z7q@&xb+bLv1}TytNf47teR34Hn?Bk9#w# z8gp|u2;k1W%9rbQ+Wi3^n(+n~*^mP^y5VnhC;Zm}YHn^G2Pwy@IOJxt7c7~ANX(}+ zsWS%+$Hx*W)aQ|CmOjUx7<2obs0bSzFzOoc2c{r}-VK6_%?WzZh2sbhpu6E+gQZG< z8EGS%#qkG_ErDdjb$Ue^_rEklZ-U@AbtfpQkHaK^8)}j%{s7dBCm1HO$!RFdmtqtn z=~S}>L5ygW! z(a7oB(zhWj4A1gRsAQ%oHrOIDCM}D>fxO8z=YT`I1$_?GILM=o7!H|4p*(IKz?6&F z3v)TXG=CVulRkQ_s<|A5(bZ#f8vHF#Fm?d#WX8-Gx|77&B|PSiJ>tMT;@={a%Qd9) z{2K(hW{T71Ut&}V@ipd#Lf2G;HY6l;5zsQ4NN97n7=0f$qGBeMk-Zk;G>M}6cGuS~ zShr?c&Eegy%5T=MxvzHld|xFNWfk!&+d_HWT#j#0R%4w#pNf;oWmrsg;cJ-uI9-W< zHCTdHW)6J9$&T#VxiiNy7Il;OwW@CvQpG}1Yb+N5WI81;VX!*d9H(<#s5IQQ{s}P@zmcd z>lBn{<>T_Ww0VI1_1HqPXR7A+5$y`rj&@*Vw=-}tz~8m|NO7sfxk|2*rFbw+%~11F z@pZ~Pmxi$J#fm}0nnp|ChN~axpc7=C`}xkJq^hZ$unTr0VN_ZeITtOW@S z?T{J0DwXxbW1J=Sq#3FcBdtlW1_6H{Ga-=}5qUN@dcDa`9uY8>C-TT(;4^S@Xi(#M z5+j7nNh*GkA0vc6j8%ruhwpyM>e}CpkqEQ^VI>C8&uGxa6EOQ!671&`Jg>@}67+XZ zsZj7U?fLkIIIrX||6&5dVg)0}S})H<*6JOI8b^GX|MKFP%Zd36S$W=+*%Kqi)36Vd z?DH_qH!DrGTO*@5gO?6sfZTWyh1H)eAKBjau?2+IHrD)qKn?PI#_9)iU^fscT1r}qRPS0|XW$tNg>PX=0X-m^ z)fv4CX%(5!blgJ>4`2=ovUGPG#j_8*hQ$Uu8+i!p2!JuSth#v88gonKjY?tCheh$V zLK@d8QAN`=L6BJ{!4R)Yc=`jFY^)jAluOj!&R-s8pxA=sLjtiF+z+SnFCTMGMMW*Wu!T68Joxc6<(~8~p?H<#7`2hWxp#z8feyw7{zv z;$cw1_ni5Y&wn(cL(M)D-?zlU?f97_9L>ZDbOmxeoDmf(RAd~x3mE6_0(i$a*dIuo zy9*d!XCpdEq1q&JFJ372gaZS5Aj01fz=nDNhe);rCeemJ6T>4YO~F8@(wq(WO|tm0-9WH;USLuU+AW!>?UbDpVRTwlnWleW=cV$&QQCOjQ<;z<;;s?k} z%_B@F^Pko!#T%YYc-?byb58_E%+QFw%(!II*F_3gMIg=z)C7zS0W<%J$-XXMi7#>R zxgs31C}?i1tgoy*v2nW|>0aH3Bb_~b@PJQ^gynlYgy1kfZiVb}Op+EURBgU4N*tc( z(Dj~JIgS+ReVcoR_|QPN#Wc?=Ir(n|;U9kG13x@+YItDEns$jV>)i)eFUNfIoBZOL z&n?){qU9XM_`5zI+ZvWKZ0g}pF&OX3k1fb({@UvLil*kpi_2;%TdK=ynyOmM>KQaG zu5YZZudHaUuR#N${)PuQVrr`DYpUxi7nHR$)ifhwnybp{TkD$3YHJq5jkT?dTjn3{o=}&`OSu8Q%xn<&DCY~^|iHSHPub?%bJ?2tIMjIDr)O$7uPMW zscJPO>lakkR5veZEUTE`i25yPswiu!tE?-lt7@&PtZ&3+>1=7NZ>evrtSxJ*YJ$$1 z`ns~ls>PLM^B2@KUJsO+k&n_m{H-WZ1D#;&pjm79=ferh{v4mGT)6E z-+Q4>h0Zp^&o~rO8nC_wTNj~Q#F0rTME$$iFGP)Y+U2RGsb0$zxA;G1WCCvU8) z3(fDE59e3cge&UN;So0+iD{FCU_VBX$#`}?O4Z?Vt<+=kZA0!d9jY6Lyt?`P)sWJm zrpxgeIZ+;1^?YL=8MjM z*7(t%;!ks|4+htDmju_91I`<+EUg}ycVY0Hb?2-Lp1UqqJb`x#6H6!M%wyg;>&{&_ z@7#Iw3ef`P~f*-$|N%Ze8|K=M!1YC=&XTrE= z4RZW~I~@H~Lvi-R!i?`WT4iGNWFxW8l+Vh>7XH8E(!G~PZ~y!qj_C(yEeC`DZXtgb zpc2`~d0_%}`9Js0gnwjZ`te_zpdXQv*|8-Yh{<1n3q)dpFn=qiT$#C?R|&>3zrZFw zUJV!x@V5#AvxX~1W|b?eC8Ml8x{{B12Kvnt53H_FAHd{peMcK}ek?YKbMKqMNTSD! zieUjDpU+--)ml!l>vG|fgZJXPnrKyfOFRAg$#t8WzP*sGG#Q2*C>tfNab>>8t^aX`=IHaddpGjQI?UzzKAgTY_utLA;x@GiH2#VXr}A4YlKp#~QqMT!mB{{;Jw? z;BA15k><}+_TL;eepw2?Gn-im3isYZZ0Z;vR>^%n`O^YKfmVKJZM`$)_r`p7fIryy z0Zg1MNj}#h0`!1=2}Bgwlz9I?4#;o3t#`@B*`D*|9p@JClHcYA#6s(RJ7d=ScCN=#;=ea$oy*`; z4MT|&Bj8Wm84Q?joBLq}pM$X8{^K|K@OxTH+?&TaZ33PDn00~U_+nX-F9=(s-lQ^* zIkSPXlDAkBJFkRO8vGZ=xWx@08t^fe1ltbFsl;txamUcd=#U};$t$h@~ zqsJ#5%28%9tV*`ah + + + Microsoft.VisualStudio.Setup.Instance + + + PSStandardMembers + + + DefaultDisplayProperty + InstanceId + + + DefaultKeyPropertySet + + InstanceId + + + + DefaultDisplayPropertySet + + InstanceId + DisplayName + InstallationVersion + InstallationPath + InstallDate + + + + + + + Microsoft.VisualStudio.Setup.PowerShell.InstanceAdapter + + + + Microsoft.VisualStudio.Setup.PackageReference + + + PSStandardMembers + + + DefaultDisplayProperty + Id + + + DefaultKeyPropertySet + + UniqueId + + + + DefaultDisplayPropertySet + + Id + Version + Chip + Language + Branch + + + + + + + diff --git a/tools/gyp/tools/vssetup.powershell/about_VSSetup.help.txt b/tools/gyp/tools/vssetup.powershell/about_VSSetup.help.txt new file mode 100644 index 00000000000000..864b5c28cdff78 --- /dev/null +++ b/tools/gyp/tools/vssetup.powershell/about_VSSetup.help.txt @@ -0,0 +1,46 @@ +TOPIC + about_vssetup + +SHORT DESCRIPTION + Enumerate and select instances of Visual Studio. + +LONG DESCRIPTION + Visual Studio 2017 introduced a new setup engine capable of installing + multiple instances of Visual Studio and other products in the Visual Studio + family. This module provides commands to enumerate those instances and + select instances that meet your criteria. For example, in a development + environment you might have a script that finds an instance of Visual Studio + with the the Managed Desktop workload for writing projects targeting the + .NET Framework. See below for more examples. + +VARIABLES + You can get the version of this module or of the query API the module uses + from the `$VSSetupVersionTable` variable. + + PS> $VSSetupVersionTable + + Name Value + ---- ----- + QueryVersion 1.15.23.19330 + ModuleVersion 2.1.2.4917 + +EXAMPLES + You can enumerate all instances - even those with errors that require a + repair - with the following command. + + Get-VSSetupInstance -All + + If you want to select all launchable instances of Visual Studio products + that have the Managed Desktop workload, use the following command. + + Get-VSSetupInstance | Get-VSSetupInstance ` + -Require 'Microsoft.VisualStudio.Workload.ManagedDesktop' + + You can also get the instance for an installation directory if you want to + discover more about what is installed to that directory. + + Get-VSSetupInstance 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community' + +SEE ALSO + https://github.com/Microsoft/vssetup.powershell + From aec215013f494130fc5ad0e3e105797a149a813f Mon Sep 17 00:00:00 2001 From: Refael Ackermann Date: Tue, 12 Mar 2019 19:56:35 -0400 Subject: [PATCH 2/3] tools: replace GYP with GYP3 (2/2) - node changes --- LICENSE | 3 ++- configure.py | 2 +- tools/gyp_node.py | 12 +++++------- tools/license-builder.sh | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/LICENSE b/LICENSE index 0990b3694b94ab..b4e9bf5c711998 100644 --- a/LICENSE +++ b/LICENSE @@ -1064,9 +1064,10 @@ The externally maintained libraries used by Node.js are: -------- """ -- GYP, located at tools/gyp, is licensed as follows: +- GYP3, located at tools/gyp, is licensed as follows: """ Copyright (c) 2009 Google Inc. All rights reserved. + Copyright (c) 2019 Refael Ackeramnn. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/configure.py b/configure.py index 15ea5687cf1cd8..a304231be180e9 100755 --- a/configure.py +++ b/configure.py @@ -24,7 +24,7 @@ CC = os.environ.get('CC', 'cc' if sys.platform == 'darwin' else 'gcc') CXX = os.environ.get('CXX', 'c++' if sys.platform == 'darwin' else 'g++') -sys.path.insert(0, os.path.join('tools', 'gyp', 'pylib')) +sys.path.insert(0, os.path.join('tools', 'gyp')) from gyp.common import GetFlavor # imports in tools/configure.d diff --git a/tools/gyp_node.py b/tools/gyp_node.py index 831d2ef1550cdb..20e36988cb6947 100755 --- a/tools/gyp_node.py +++ b/tools/gyp_node.py @@ -6,7 +6,7 @@ script_dir = os.path.dirname(__file__) node_root = os.path.normpath(os.path.join(script_dir, os.pardir)) -sys.path.insert(0, os.path.join(node_root, 'tools', 'gyp', 'pylib')) +sys.path.insert(0, os.path.join(node_root, 'tools', 'gyp')) import gyp # Directory within which we want all generated files (including Makefiles) @@ -34,13 +34,11 @@ def run_gyp(args): args.append('--depth=' + node_root) - # There's a bug with windows which doesn't allow this feature. - if sys.platform != 'win32' and 'ninja' not in args: - # Tell gyp to write the Makefiles into output_dir - args.extend(['--generator-output', output_dir]) + # Tell gyp to write the Makefiles into output_dir + args.extend(['--generator-output', output_dir]) - # Tell make to write its output into the same dir - args.extend(['-Goutput_dir=' + output_dir]) + # Tell make to write its output into the same dir + args.extend(['-Goutput_dir=' + output_dir]) args.append('-Dcomponent=static_library') args.append('-Dlibrary=static_library') diff --git a/tools/license-builder.sh b/tools/license-builder.sh index d4c39203884df3..22fde511793bad 100755 --- a/tools/license-builder.sh +++ b/tools/license-builder.sh @@ -74,7 +74,7 @@ addlicense "zlib" "deps/zlib" \ addlicense "npm" "deps/npm" "$(cat ${rootdir}/deps/npm/LICENSE)" # Build tools -addlicense "GYP" "tools/gyp" "$(cat ${rootdir}/tools/gyp/LICENSE)" +addlicense "GYP3" "tools/gyp" "$(cat ${rootdir}/tools/gyp/LICENSE)" addlicense "inspector_protocol" "tools/inspector_protocol" "$(cat ${rootdir}/tools/inspector_protocol/LICENSE)" addlicense "jinja2" "tools/inspector_protocol/jinja2" "$(cat ${rootdir}/tools/inspector_protocol/jinja2/LICENSE)" addlicense "markupsafe" "tools/inspector_protocol/markupsafe" "$(cat ${rootdir}/tools/inspector_protocol/markupsafe/LICENSE)" From 28b14ec0d67aa9be4ce16558cd4d860473f80f38 Mon Sep 17 00:00:00 2001 From: Refael Ackermann Date: Thu, 30 May 2019 19:28:06 -0400 Subject: [PATCH 3/3] fixup! keep output dir on Windows --- tools/gyp_node.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/gyp_node.py b/tools/gyp_node.py index 20e36988cb6947..c3c83c975f2935 100755 --- a/tools/gyp_node.py +++ b/tools/gyp_node.py @@ -11,7 +11,10 @@ # Directory within which we want all generated files (including Makefiles) # to be written. -output_dir = os.path.join(os.path.abspath(node_root), 'out') +if sys.platform == 'win32': + output_dir = '.' +else: + output_dir = os.path.join(os.path.abspath(node_root), 'out') def run_gyp(args): # GYP bug.