-
Notifications
You must be signed in to change notification settings - Fork 284
/
Copy pathPyTypeUtils.cmake
593 lines (531 loc) · 19.3 KB
/
PyTypeUtils.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
# Find the python interpreter first so that Python libs corresponding to the
# version of this interpreter can be found below.
find_package(PythonInterp)
if (NOT PYTHONINTERP_FOUND)
message(FATAL_ERROR "Python interpreter not found.")
endif()
find_package(PythonLibs)
if(NOT PYTHONLIBS_FOUND)
message(FATAL_ERROR "PyType requires Python developer libraries (https://packages.ubuntu.com/python-dev).")
endif()
set(COPY_SCRIPT "${PROJECT_SOURCE_DIR}/build_scripts/pytype_copy.py")
set(TEST_MODULE_SCRIPT "${PROJECT_SOURCE_DIR}/build_scripts/test_module.py")
set(PYEXE_SCRIPT "${PROJECT_SOURCE_DIR}/build_scripts/pyexe.py")
set(CC_TEST_SCRIPT "${PROJECT_SOURCE_DIR}/build_scripts/run_cc_test.py")
include(CMakeParseArguments)
# Set up the target that depends on all tests: "test_all"
# As well as sharded targets that run only a roughly equal subset of tests,
# such as "test_all_shard_1_of_3".
add_custom_target("test_all")
set(ALL_TESTS_SHARD_COUNT 3)
foreach(i RANGE 1 ${ALL_TESTS_SHARD_COUNT})
add_custom_target("test_all_shard_${i}_of_${ALL_TESTS_SHARD_COUNT}")
endforeach()
# Add a target to "test_all" and to its computed "test_all_shard_*" target.
function(_add_to_all_tests fq_target_name)
add_dependencies("test_all" ${fq_target_name})
string(SHA256 hash_of_target_name ${fq_target_name})
string(SUBSTRING ${hash_of_target_name} 56 8 hash_of_target_name)
math(EXPR modulo_of_target_name "(0x${hash_of_target_name} % ${ALL_TESTS_SHARD_COUNT}) + 1")
add_dependencies("test_all_shard_${modulo_of_target_name}_of_${ALL_TESTS_SHARD_COUNT}" ${fq_target_name})
endfunction()
string(COMPARE EQUAL "${CMAKE_BUILD_TYPE}" "Debug" is_debug_build)
if(is_debug_build)
add_definitions(-DPYTYPE_ENABLE_CPP_LOGGING)
endif(is_debug_build)
# Returns the fully qualified parent name for targets in the current source
# directory in |fq_parent_name|.
function(_gen_fq_target_parent_name fq_parent_name)
# Strip the prefix so that names are all relative to the project root directory.
string(REPLACE "${PROJECT_SOURCE_DIR}/" "" relative_path ${CMAKE_CURRENT_SOURCE_DIR})
string(REPLACE "/" "." dotted_path ${relative_path})
set(${fq_parent_name} ${dotted_path} PARENT_SCOPE)
endfunction(_gen_fq_target_parent_name fq_parent_name)
# Given a local target name in |name|, returns the fully qualified target name
# in |fq_target_name|.
function(_gen_fq_target_name name fq_target_name)
string(FIND ${name} "." dot_location)
if(${dot_location} GREATER "-1")
message(FATAL_ERROR "Target name should not have a '.' in it.")
endif()
_gen_fq_target_parent_name(parent_fq_name)
set(${fq_target_name} "${parent_fq_name}.${name}" PARENT_SCOPE)
endfunction(_gen_fq_target_name name fq_target_name)
# Given a |target_name| referenced from the current source directory, it
# evaluates and returns the fully qualified name of the target in
# |fq_target_name|. Note that a target name referenced from the current
# directory can either be a local target name, or a fully qualified global
# target name.
function(_eval_fq_target_name target_name fq_target_name)
string(FIND ${target_name} "." dot_location)
if(${dot_location} EQUAL 0)
# This is a local target to prefix the parent name
_gen_fq_target_parent_name(parent_name)
set(${fq_target_name} "${parent_name}${target_name}" PARENT_SCOPE)
else()
# This is an absolute target so just return the target name as is.
set(${fq_target_name} ${target_name} PARENT_SCOPE)
endif()
endfunction(_eval_fq_target_name target_name fq_target_name)
# Given a fully qualifed target name |fq_target_name|, and a list of file names
# relative to the current directory, this function adds a list of the absolute
# paths to these files as the property "OUT" to the target.
function(_add_out_property fq_target_name relative_filename_list)
set(absolute_filename_list "")
foreach(src IN LISTS relative_filename_list)
list(APPEND absolute_filename_list "${CMAKE_CURRENT_BINARY_DIR}/${src}")
endforeach(src)
set_target_properties(
${fq_target_name}
PROPERTIES
OUT "${absolute_filename_list}"
)
endfunction(_add_out_property local_target_name out_file_list)
# Given a list of |targets|, the list of their "OUT" property are returned
# in a var named by |out_property_list|.
function(_get_out_property_list targets out_property_list)
set(out_list "")
if(targets)
foreach(tgt IN LISTS targets)
_eval_fq_target_name(${tgt} fq_target_name)
list(APPEND out_list $<TARGET_PROPERTY:${fq_target_name},OUT>)
endforeach(tgt)
endif()
set(${out_property_list} "${out_list}" PARENT_SCOPE)
endfunction(_get_out_property_list targets out_property_list)
# Function implementing a 'genbison' rule which invokes bison over a source
# file.
# The 'genbison' rule requires the following arguments:
# NAME - The local name of the target for this rule.
# SRC - The .yy file in the current directory.
# HDR_OUT - The name of the bison generated header file.
# CC_OUT - The name of bison generated cc file.
function(genbison)
cmake_parse_arguments(
GENBISON # prefix
"" # optional args
"NAME;SRC;HDR_OUT;CC_OUT" # single value args
"" # multi-value args
${ARGN}
)
if(NOT GENBISON_NAME)
message(FATAL_ERROR "'genbison' rule requires a NAME argument specifying the target name.")
endif()
if(NOT GENBISON_SRC)
message(FATAL_ERROR "'genbison' rule requires a SRC argument specifying the .yy file.")
endif()
if(NOT GENBISON_HDR_OUT)
message(FATAL_ERROR "'genbison' rule requires a HDR_OUT argument specifying the name of the generated header file.")
endif()
if(NOT GENBISON_CC_OUT)
message(FATAL_ERROR "'genbison' rule requires a CC_OUT argument specifying the name of the generated .cc file.")
endif()
_gen_fq_target_name(${GENBISON_NAME} fq_target_name)
set(CC_OUT "${CMAKE_CURRENT_BINARY_DIR}/${GENBISON_CC_OUT}")
set(HDR_OUT "${CMAKE_CURRENT_BINARY_DIR}/${GENBISON_HDR_OUT}")
BISON_TARGET(
${fq_target_name}
"${CMAKE_CURRENT_SOURCE_DIR}/${GENBISON_SRC}"
${CC_OUT}
DEFINES_FILE ${HDR_OUT}
COMPILE_FLAGS --language=c++
)
# The BISON_TARGET function does not create a target.
# So, we create a dummy target which consumes the bison output.
add_custom_target(
${fq_target_name}
ALL
SOURCES "${BISON_${fq_target_name}_OUTPUTS}"
)
# We add convenience properties to the target so that properties
# like the generated header or cc file output can be retrieved for
# use with, say, flex targets.
set_target_properties(
${fq_target_name}
PROPERTIES
HDR_OUT ${HDR_OUT}
CC_OUT ${CC_OUT}
)
endfunction(genbison)
# Function implementing a 'genflex' rule which invokes flex over a source file.
# The 'genflex' rule requires the following arguments:
# NAME - The local name of the target for this rule.
# SRC - The .lex file on which flex should be invoked.
# CC_OUT - The generated .cc file.
# BISON_DEP - The bison target whose outputs are consumed by this flex target.
function(genflex)
cmake_parse_arguments(
GENFLEX # prefix
"" # optional args
"NAME;SRC;CC_OUT;BISON_DEP" # single value args
"" # multi-value args
${ARGN}
)
if(NOT GENFLEX_NAME)
message(FATAL_ERROR "'genflex' rule requires a NAME argument.")
endif()
if(NOT GENFLEX_CC_OUT)
message(FATAL_ERROR "'genflex' rule requires a CC_OUT argument specifying the name of the generated .cc file.")
endif()
if(NOT GENFLEX_BISON_DEP)
message(FATAL_ERROR "'genflex' rule requires a BISON_DEP argument specifying the 'genbison' target whose outputs should be fed to this 'genflex' target.")
endif()
if(NOT GENFLEX_SRC)
message(FATAL_ERROR "'genflex' rule requires a SRC argument specifying the .lex file")
endif()
_gen_fq_target_name(${GENFLEX_NAME} fq_target_name)
set(cc_out "${CMAKE_CURRENT_BINARY_DIR}/${GENFLEX_CC_OUT}")
FLEX_TARGET(
${fq_target_name}
"${CMAKE_CURRENT_SOURCE_DIR}/${GENFLEX_SRC}"
${cc_out}
)
add_custom_target(
${fq_target_name}
ALL
SOURCES "${FLEX_${fq_target_name}_OUTPUTS}"
)
# Add the bison target as a dependency to this flex target so that
# the bison outputs are ready before flex is run.
_eval_fq_target_name(${GENFLEX_BISON_DEP} fq_bison_target_name)
add_dependencies(${fq_target_name} ${fq_bison_target_name})
set_target_properties(
${fq_target_name}
PROPERTIES
CC_OUT ${cc_out}
)
endfunction(genflex)
# A function implementing a 'cc_library' rule which builds a C++ static library.
# The 'cc_library' rule takes the following arguments:
# NAME - The name of the target. This is a required argument.
# SRCS - List of .cc files of the library. This is a required argument.
# HDRS - List of .h files of the library.
# DEPS - Other cc_library targets this library depends on.
#
# TODO(sivachandra): Implement a header only library rule.
# CMake does not support header only libraries via its builtin utilities. Since
# Pytype uses header only library targets, having rules to setup header only
# library targets helps in setting up the dependencies correctly.
function(cc_library)
cmake_parse_arguments(
CC_LIBRARY # prefix
"" # optional args
"NAME" # single value args
"SRCS;HDRS;DEPS" # multi-value args
${ARGN}
)
if(NOT CC_LIBRARY_NAME)
message(FATAL_ERROR "'cc_library' rule requires a NAME argument.")
endif()
_gen_fq_target_name(${CC_LIBRARY_NAME} fq_target_name)
add_library(
${fq_target_name}
${CC_LIBRARY_SRCS}
${CC_LIBRARY_HDRS}
)
target_include_directories(
${fq_target_name}
PUBLIC
${PYTHON_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}
)
set_target_properties(
${fq_target_name}
PROPERTIES
LINKER_LANGUAGE CXX
OUTPUT_NAME ${CC_LIBRARY_NAME}
)
if(CC_LIBRARY_DEPS)
foreach(dep IN LISTS CC_LIBRARY_DEPS)
_eval_fq_target_name(${dep} fq_dep_name)
target_link_libraries(${fq_target_name} ${fq_dep_name})
endforeach(dep)
endif(CC_LIBRARY_DEPS)
endfunction(cc_library)
# A function implementing a 'cc_test' rule which builds a C++ test suite binary
# and runs it.
# The 'cc_test' rule takes the following arguments:
# NAME - The name of the target. This is a required argument.
# SRCS - List of .cc files of the test. This is a required argument.
# DEPS - List of cc_library targets this test depends on.
function(cc_test)
cmake_parse_arguments(
CC_TEST # prefix
"" # optional args
"NAME" # single value args
"SRCS;DEPS" # multi-value args
${ARGN}
)
if(NOT CC_TEST_NAME)
message(FATAL_ERROR "'cc_test' rule requires a NAME argument.")
endif()
if(NOT CC_TEST_SRCS)
message(FATAL_ERROR "'cc_test' rule requires a SRCS argument specifying the list of .cc files of the test.")
endif()
_gen_fq_target_name("${CC_TEST_NAME}___runner_internal" fq_runner_target_name)
_gen_fq_target_name(${CC_TEST_NAME} fq_target_name)
add_executable(
${fq_runner_target_name}
${CC_TEST_SRCS}
)
target_include_directories(
${fq_runner_target_name}
PUBLIC
${PYTHON_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}
${PROJECT_SOURCE_DIR}/googletest/googlemock/include
${PROJECT_SOURCE_DIR}/googletest/googletest/include
)
if(CC_TEST_DEPS)
foreach(dep IN LISTS CC_TEST_DEPS)
_eval_fq_target_name(${dep} fq_dep_name)
target_link_libraries(${fq_runner_target_name} ${fq_dep_name})
endforeach(dep)
endif()
target_link_libraries(
${fq_runner_target_name}
${PYTHON_LIBRARIES}
gtest_main
gmock_main
)
# Add a target to run the executable built above.
set_target_properties(
${fq_runner_target_name}
PROPERTIES
PREFIX ""
SUFFIX ".exe"
OUTPUT_NAME "${CC_TEST_NAME}"
)
set(log_file "${CC_TEST_NAME}.log")
add_custom_command(
OUTPUT ${log_file}
COMMAND ${CC_TEST_SCRIPT} -t ${fq_target_name} -b "${CMAKE_CURRENT_BINARY_DIR}/${CC_TEST_NAME}.exe" -l "${CMAKE_CURRENT_BINARY_DIR}/${log_file}"
DEPENDS ${fq_runner_target_name}
)
add_custom_target(
${fq_target_name}
DEPENDS ${log_file}
)
_add_to_all_tests(${fq_target_name})
endfunction(cc_test)
# Function implementing a rule 'py_extension' to compile a set of CC and headers
# files into a Python extension module.
# The 'py_extension' rule requires the following arguments:
# NAME - The local name of the target.
# SRCS - A list of sources which have to be compiled in to a Python extension
# module.
#
# The rule also takes an optionl DEPS argument which is the list of targets
# on which this 'py_extension' target depends.
function(py_extension)
cmake_parse_arguments(
PY_EXTENSION # prefix
""
"NAME" # single value args
"SRCS;DEPS" # multi-value args
${ARGN}
)
if(NOT PY_EXTENSION_NAME)
message(FATAL_ERROR "'py_extension' rule requires a NAME argument.")
endif()
if(NOT PY_EXTENSION_SRCS)
message(FATAL_ERROR "'py_extension' rule requires a SRCS argument.")
endif()
_gen_fq_target_name(${PY_EXTENSION_NAME} fq_target_name)
add_library(
${fq_target_name}
SHARED # We want a py_extension library to be an shared library
${PY_EXTENSION_SRCS}
)
set_target_properties(
${fq_target_name}
PROPERTIES
PREFIX ""
OUTPUT_NAME ${PY_EXTENSION_NAME}
)
target_include_directories(
${fq_target_name}
PRIVATE
${PYTHON_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}
${PROJECT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
)
target_link_libraries(
${fq_target_name}
${PYTHON_LIBRARIES}
)
# Add the deps if specified
if(PY_EXTENSION_DEPS)
foreach(dep IN LISTS PY_EXTENSION_DEPS)
_eval_fq_target_name(${dep} fq_dep_name)
add_dependencies(${fq_target_name} ${fq_dep_name})
endforeach(dep)
endif()
endfunction(py_extension)
function(py_library)
cmake_parse_arguments(
PY_LIBRARY # prefix
"" # optional args
"NAME" # single value args
"SRCS;DEPS" # multi-value args
${ARGN}
)
if(NOT PY_LIBRARY_NAME)
message(FATAL_ERROR "'py_library' rule requires a NAME argument.")
endif()
_get_out_property_list("${PY_LIBRARY_DEPS}" deps_out)
if(PY_LIBRARY_SRCS)
# Add a command which copies the listed sources over to the current build
# directory.
add_custom_command(
OUTPUT ${PY_LIBRARY_SRCS}
COMMAND ${PYTHON_EXECUTABLE} -B ${COPY_SCRIPT} -s ${CMAKE_CURRENT_SOURCE_DIR} -d ${CMAKE_CURRENT_BINARY_DIR} ${PY_LIBRARY_SRCS}
DEPENDS ${PY_LIBRARY_SRCS} ${deps_out}
)
endif()
_gen_fq_target_name(${PY_LIBRARY_NAME} fq_target_name)
add_custom_target(
${fq_target_name}
ALL
DEPENDS ${PY_LIBRARY_SRCS}
)
# Add the deps if specified
if(PY_LIBRARY_DEPS)
foreach(dep IN LISTS PY_LIBRARY_DEPS)
_eval_fq_target_name(${dep} fq_dep_name)
add_dependencies(${fq_target_name} ${fq_dep_name})
endforeach(dep)
endif()
_add_out_property(${fq_target_name} "${PY_LIBRARY_SRCS}")
endfunction(py_library)
function(toplevel_py_binary)
cmake_parse_arguments(
PY_BINARY # prefix
"" # optional args
"NAME;MAIN" # single value args
"SRCS;DEPS" # multi-value args
${ARGN}
)
if(NOT PY_BINARY_NAME)
message(FATAL_ERROR "'py_binary' rule requires a NAME argument.")
endif()
if(NOT PY_BINARY_SRCS)
message(FATAL_ERROR "'py_binary' rule requires a SRCS argument.")
endif()
if(NOT PY_BINARY_MAIN)
message(FATAL_ERROR "'py_binary' rule requires a MAIN argument.")
endif()
if(PY_BINARY_DEPS)
set(deps "DEPS ${PY_BINARY_DEPS}")
endif()
set(lib_suffix "___internal_py_library_for_binary")
set(py_binary_library_name ${PY_BINARY_NAME}${lib_suffix})
py_library(
NAME
${py_binary_library_name}
SRCS
${PY_BINARY_SRCS}
DEPS
${PY_BINARY_DEPS}
)
_gen_fq_target_name(${py_binary_library_name} py_binary_library_fq_name)
_get_out_property_list(${py_binary_library_fq_name} out_file_list)
string(REPLACE "${PROJECT_SOURCE_DIR}/" "" relative_path_to_main ${CMAKE_CURRENT_SOURCE_DIR}/${PY_BINARY_MAIN})
string(REPLACE ".py" "" relative_path_to_main_no_ext ${relative_path_to_main})
string(REPLACE "/" "." main_module ${relative_path_to_main_no_ext})
set(exe_path ${PYTYPE_OUT_BIN_DIR}/${PY_BINARY_NAME})
# Copy the main script to a file with the name of the target name.
add_custom_command(
OUTPUT ${exe_path}
COMMAND ${PYTHON_EXECUTABLE} ${PYEXE_SCRIPT} -p ${PROJECT_BINARY_DIR} -v TYPESHED_HOME=${PROJECT_SOURCE_DIR}/typeshed -m ${main_module} -x ${exe_path}
DEPENDS ${out_file_list} # This command should run if the internal py_library was built.
)
_gen_fq_target_name(${PY_BINARY_NAME} fq_target_name)
add_custom_target(
${fq_target_name}
ALL
DEPENDS ${exe_path}
)
endfunction(toplevel_py_binary)
function(py_test)
cmake_parse_arguments(
PY_TEST # prefix
"" # optional args
"NAME" # single value args
"SRCS;DEPS" # multi-value args
${ARGN}
)
if(NOT PY_TEST_NAME)
message(FATAL_ERROR "'py_test' rule requires a NAME argument.")
endif()
_gen_fq_target_name(${PY_TEST_NAME} fq_target_name)
set(lib_suffix "___internal_py_library_for_test")
py_library(
NAME
"${PY_TEST_NAME}${lib_suffix}"
SRCS
${PY_TEST_SRCS}
DEPS
${PY_TEST_DEPS}
)
_get_out_property_list(${fq_target_name}${lib_suffix} lib_out)
add_custom_command(
OUTPUT ${PY_TEST_NAME}.log
COMMAND ${CMAKE_COMMAND} -E env TYPESHED_HOME=${PROJECT_SOURCE_DIR}/typeshed ${PYTHON_EXECUTABLE} -B
${TEST_MODULE_SCRIPT} ${fq_target_name} -o ${CMAKE_CURRENT_BINARY_DIR}/${PY_TEST_NAME}.log -P ${PROJECT_BINARY_DIR} -s -p
DEPENDS ${lib_out}
)
add_custom_target(
${fq_target_name}
DEPENDS ${PY_TEST_NAME}.log
)
# The internal py_library target should be a dep for this target.
add_dependencies(${fq_target_name} "${fq_target_name}${lib_suffix}")
# Add the deps if specified
if(PY_TEST_DEPS)
foreach(dep IN LISTS PY_TEST_DEPS)
_eval_fq_target_name(${dep} fq_dep_name)
add_dependencies(${fq_target_name} ${fq_dep_name})
endforeach(dep)
endif()
_add_to_all_tests(${fq_target_name})
endfunction(py_test)
function(filegroup)
cmake_parse_arguments(
FILEGROUP # prefix
"" # optional args
"NAME" # single value args
"SRCS" # multi-value args
${ARGN}
)
if(NOT FILEGROUP_NAME)
message(FATAL_ERROR "'filegroup' rule requires a NAME argument.")
endif()
if(NOT FILEGROUP_SRCS)
message(FATAL_ERROR "'filegroup' rule requires a SRCS argument.")
endif()
# Add a command which copies the listed sources over to the current build
# directory.
add_custom_command(
OUTPUT ${FILEGROUP_SRCS}
COMMAND ${PYTHON_EXECUTABLE} -B ${COPY_SCRIPT} -s ${CMAKE_CURRENT_SOURCE_DIR} -d ${CMAKE_CURRENT_BINARY_DIR} ${FILEGROUP_SRCS}
DEPENDS ${FILEGROUP_SRCS}
)
_gen_fq_target_name(${FILEGROUP_NAME} fq_target_name)
add_custom_target(
${fq_target_name}
ALL
DEPENDS ${FILEGROUP_SRCS}
)
endfunction(filegroup)
# Add an __init__.py file to the current binary directory.
# TODO(sivachandra): Make this rule use the __init__.py from the current source
# directory if present. Currently, none of Pytype's __init__.py files have any
# functionality. So, just creating an empty __init__.py is sufficient.
function(add_package)
# TODO(sivachandra): Make this function create a real target on which all
# py_library targets in the directory will implicitly depend on.
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/__init__.py" "\n")
endfunction(add_package)