Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(37)

Side by Side Diff: docs/scripts/ninja_options_script.py

Issue 2006563002: Moved Sublime documentation to markdown and added SublimeClang setup (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 #!/usr/bin/python
2 # Copyright 2016 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5 #
6 # Usage within SublimeClang:
7 # "sublimeclang_options_script": "python /path/to/ninja_options_script.py \
alancutter (OOO until 2018) 2016/05/23 07:31:03 This could be ${project_path}/src/docs/scripts/nin
8 # ${project_path}/src \
9 # ${project_path}/src/out/Debug"
alancutter (OOO until 2018) 2016/05/23 07:31:03 Mention that ${project_path} expands to the direct
10
11 import fnmatch
12 import logging
13 import os
14 import sys
15
16 # Change to an absolute reference if ninja is not on your path
17 path_to_ninja = 'ninja'
18
19 # Ninja file options to extract (add 'cflags' if you need the c flags too,
20 # although these usually break things)
21 ninja_file_options = ['defines', 'include_dirs', 'cflags_cc']
22
23 def merge_options_dicts(options_dict_1, options_dict_2):
24 '''
25 Given two dictionaries of options, returns one dictionary with both sets of
26 options appended together.
27
28 Both dictionaries must have the same options, even if some of them are empty
29 lists.
30 '''
31 assert set(options_dict_1.keys()) == set(options_dict_2.keys()), \
32 "Both options dicts must have the same keys"
33 final_options_dict = {}
34 for key in options_dict_1:
35 final_options_dict[key] = options_dict_1[key] + options_dict_2[key]
36 return final_options_dict
37
38 def extract_options_from_ninja_file(ninja_file_path, options_to_extract):
39 '''
40 Extracts the given options from the file at ninja_file_path and returns them
41 as a dictionary.
42 '''
43 extracted_options = dict((o, []) for o in options_to_extract)
44 for line in open(ninja_file_path):
45 for option in options_to_extract:
46 if line.strip().startswith(option):
47 extracted_options[option] += line.split('=', 1)[1].split()
48 return extracted_options
49
50 def find_ninja_file_options(ninja_root_path, relative_file_path_to_find,
51 options_to_extract):
52 '''
53 Returns a dictionary of the given extracted options for the ninja file for
54 relative_file_path_to_find.
55
56 The options are extracted from the first *.ninja file in ninja_root_path that
57 contains relative_file_path_to_find. Otherwise, the first *.ninja file that
58 contains relative_file_path_to_find without the file extension. Otherwise, the
59 script walks up directories until it finds ninja files and then concatenates
60 the found options from all of them.
61 '''
62 matches = []
63 for root, dirnames, filenames in os.walk(ninja_root_path):
64 for filename in fnmatch.filter(filenames, '*.ninja'):
65 matches.append(os.path.join(root, filename))
66 logging.debug("Found %d Ninja targets", len(matches))
67
68 # First, look for a *.ninja file containing the full filename.
69 for ninja_file in matches:
70 for line in open(ninja_file):
71 if relative_file_path_to_find in line:
72 return extract_options_from_ninja_file(ninja_file, options_to_extract)
73
74 # Next, look for a *.ninja file containing the basename (no extension).
75 # This is a fix for header files with a corresponding cpp file.
76 for ninja_file in matches:
77 for line in open(ninja_file):
78 if os.path.splitext(relative_file_path_to_find)[0] in line:
79 all_options = extract_options_from_ninja_file(ninja_file,
80 options_to_extract)
81 if all_options['include_dirs']:
82 return all_options
83
84 # Finally, open any *.ninja files in the directory or higher.
85 current_path = os.path.join(ninja_root_path, 'obj',
86 os.path.dirname(relative_file_path_to_find))
87 while current_path != ninja_root_path:
88 if os.path.exists(current_path):
89 matches = []
90 for root, dirnames, filenames in os.walk(ninja_root_path):
91 for filename in fnmatch.filter(filenames, '*.ninja'):
92 matches.append(os.path.join(root, filename))
93 logging.debug("Found %d Ninja targets", len(matches))
94
95 matches = []
96 for match in os.listdir(current_path):
97 if match.endswith('.ninja'):
98 matches.append(os.path.join(current_path, match))
99 all_options = dict((o, []) for o in matches)
100 for ninja_file in ninja_files_in_current_path:
101 all_options = merge_options_dicts(all_options,
102 extract_options_from_ninja_file(ninja_file, options_to_extract))
103 # As soon as we have some include_dirs from the ninja files, return.
104 if all_options['include_dirs']:
105 return all_options
106 current_path = os.path.dirname(current_path)
107
108 return None
109
110 project_path = sys.argv[1]
111 build_path = sys.argv[2]
112 file_path = sys.argv[3]
alancutter (OOO until 2018) 2016/05/23 07:31:03 The example in the comment at the top only passes
113
114 logging.debug("Compiling file %s\n", file_path)
115 # The file must be somewhere under the project folder...
116 if not file_path.lower().startswith(project_path.lower()):
117 logging.error("File %s is not in current project folder %s\n",
118 (file_path, project_path))
119 sys.exit(1)
120 file_relative_path = os.path.relpath(file_path, project_path)
121
122 # Look for a .ninja file that contains our current file, since the ninja
123 # project file name is needed to construct the full Ninja target path.
124 logging.debug("Searching for Ninja target")
125 options = find_ninja_file_options(build_path, file_relative_path,
126 ninja_file_options)
127 if not options:
128 logging.error("File %s is not in any Ninja file under %s",
129 (file_relative_path, build_path))
130 sys.exit(2)
131
132 for option in ninja_file_options:
133 for piece in options[option]:
134 # Resolve relative includes
135 if piece.startswith('-I'):
136 print('-I' + os.path.join(build_path, piece[2:]))
137 else:
138 print(piece)
OLDNEW
« docs/scripts/compile_current_file.py ('K') | « docs/scripts/compile_current_file.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698