-
Notifications
You must be signed in to change notification settings - Fork 195
/
Public.cmake
489 lines (427 loc) · 17.8 KB
/
Public.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
#
# Copyright 2016 Pixar
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
include(Private)
function(pxr_library NAME)
set(options
DISABLE_PRECOMPILED_HEADERS
MAYA_PLUGIN
)
set(oneValueArgs
TYPE
PRECOMPILED_HEADER_NAME
)
set(multiValueArgs
PUBLIC_CLASSES
PUBLIC_HEADERS
PRIVATE_CLASSES
PRIVATE_HEADERS
CPPFILES
LIBRARIES
INCLUDE_DIRS
RESOURCE_FILES
PYTHON_PUBLIC_CLASSES
PYTHON_PRIVATE_CLASSES
PYTHON_PUBLIC_HEADERS
PYTHON_PRIVATE_HEADERS
PYTHON_CPPFILES
PYMODULE_CPPFILES
PYMODULE_FILES
PYSIDE_UI_FILES
)
cmake_parse_arguments(args
"${options}"
"${oneValueArgs}"
"${multiValueArgs}"
${ARGN}
)
# Merge the python specific categories with the more general before setting
# up compilation.
if(args_PYTHON_PUBLIC_CLASSES)
list(APPEND args_PUBLIC_CLASSES ${args_PYTHON_PUBLIC_CLASSES})
endif()
if(args_PYTHON_PUBLIC_HEADERS)
list(APPEND args_PUBLIC_HEADERS ${args_PYTHON_PUBLIC_HEADERS})
endif()
if(args_PYTHON_PRIVATE_CLASSES)
list(APPEND args_PRIVATE_CLASSES ${args_PYTHON_PRIVATE_CLASSES})
endif()
if(args_PYTHON_PRIVATE_HEADERS)
list(APPEND args_PRIVATE_HEADERS ${args_PYTHON_PRIVATE_HEADERS})
endif()
if(args_PYTHON_CPPFILES)
list(APPEND args_CPPFILES ${args_PYTHON_CPPFILES})
endif()
# Collect libraries.
if(NOT args_TYPE STREQUAL "PLUGIN")
get_property(help CACHE PXR_ALL_LIBS PROPERTY HELPSTRING)
list(APPEND PXR_ALL_LIBS ${NAME})
set(PXR_ALL_LIBS "${PXR_ALL_LIBS}" CACHE INTERNAL "${help}")
if(args_TYPE STREQUAL "STATIC")
# Note if this library is explicitly STATIC.
get_property(help CACHE PXR_STATIC_LIBS PROPERTY HELPSTRING)
list(APPEND PXR_STATIC_LIBS ${NAME})
set(PXR_STATIC_LIBS "${PXR_STATIC_LIBS}" CACHE INTERNAL "${help}")
endif()
endif()
# Expand classes into filenames.
_classes(${NAME} ${args_PRIVATE_CLASSES} PRIVATE)
_classes(${NAME} ${args_PUBLIC_CLASSES} PUBLIC)
# Custom tweaks.
if(args_TYPE STREQUAL "PLUGIN")
# We can't build plugins if we're not building shared libraries.
if(NOT TARGET shared_libs)
message(STATUS "Skipping plugin ${NAME}, shared libraries required")
return()
endif()
set(prefix "")
set(suffix ${CMAKE_SHARED_LIBRARY_SUFFIX})
# Maya plugins require the .mll suffix on Windows and .bundle on OSX.
if(args_MAYA_PLUGIN)
if (WIN32)
set(suffix ".mll")
elseif(IS_MACOSX)
set(suffix ".bundle")
endif()
endif()
else()
# If the caller didn't specify the library type then choose the
# type now.
if("x${args_TYPE}" STREQUAL "x")
if(BUILD_SHARED_LIBS)
set(args_TYPE "SHARED")
else()
set(args_TYPE "STATIC")
endif()
endif()
set(prefix "${CMAKE_SHARED_LIBRARY_PREFIX}")
if(args_TYPE STREQUAL "STATIC")
set(suffix ${CMAKE_STATIC_LIBRARY_SUFFIX})
else()
set(suffix ${CMAKE_SHARED_LIBRARY_SUFFIX})
endif()
endif()
set(pch "ON")
if(args_DISABLE_PRECOMPILED_HEADERS)
set(pch "OFF")
endif()
_pxr_library(${NAME}
TYPE "${args_TYPE}"
PREFIX "${prefix}"
SUFFIX "${suffix}"
SUBDIR "${subdir}"
CPPFILES "${args_CPPFILES};${${NAME}_CPPFILES}"
PUBLIC_HEADERS "${args_PUBLIC_HEADERS};${${NAME}_PUBLIC_HEADERS}"
PRIVATE_HEADERS "${args_PRIVATE_HEADERS};${${NAME}_PRIVATE_HEADERS}"
LIBRARIES "${args_LIBRARIES}"
INCLUDE_DIRS "${args_INCLUDE_DIRS}"
RESOURCE_FILES "${args_RESOURCE_FILES}"
PRECOMPILED_HEADERS "${pch}"
PRECOMPILED_HEADER_NAME "${args_PRECOMPILED_HEADER_NAME}"
LIB_INSTALL_PREFIX_RESULT libInstallPrefix
)
if(args_PYMODULE_CPPFILES OR args_PYMODULE_FILES OR args_PYSIDE_UI_FILES)
_pxr_python_module(
${NAME}
WRAPPED_LIB_INSTALL_PREFIX "${INSTALL_DIR_SUFFIX}/${libInstallPrefix}"
PYTHON_FILES ${args_PYMODULE_FILES}
PYSIDE_UI_FILES ${args_PYSIDE_UI_FILES}
CPPFILES ${args_PYMODULE_CPPFILES}
INCLUDE_DIRS ${args_INCLUDE_DIRS}
PRECOMPILED_HEADERS ${pch}
PRECOMPILED_HEADER_NAME ${args_PRECOMPILED_HEADER_NAME}
)
endif()
endfunction()
macro(pxr_shared_library NAME)
pxr_library(${NAME} TYPE "SHARED" ${ARGN})
endmacro(pxr_shared_library)
macro(pxr_plugin NAME)
pxr_library(${NAME} TYPE "PLUGIN" ${ARGN})
endmacro(pxr_plugin)
function(pxr_setup_python)
# Install a pxr __init__.py in order to have Python
# see UsdMaya module inside pxr subdirectory
_get_install_dir(lib/python/pxr installPrefix)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/__init__.py"
"try:\n __import__('pkg_resources').declare_namespace(__name__)\nexcept:\n from pkgutil import extend_path\n __path__ = extend_path(__path__, __name__)\n")
execute_process(COMMAND ${Python_EXECUTABLE} -m compileall ${CMAKE_CURRENT_BINARY_DIR}/__init__.py)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/__init__.py
DESTINATION
${INSTALL_DIR_SUFFIX}/${installPrefix}
)
endfunction() # pxr_setup_python
function(pxr_test_scripts)
# If we can't build Python modules then do nothing.
if(NOT TARGET python)
return()
endif()
if (NOT BUILD_TESTS)
return()
endif()
foreach(file ${ARGN})
get_filename_component(destFile ${file} NAME_WE)
# XXX -- We shouldn't have to install to run tests.
install(
PROGRAMS ${file}
DESTINATION ${INSTALL_DIR_SUFFIX}/tests
RENAME ${destFile}
)
endforeach()
endfunction() # pxr_test_scripts
function(pxr_install_test_dir)
if (BUILD_TESTS)
cmake_parse_arguments(bt
""
"SRC;DEST"
""
${ARGN}
)
# XXX -- We shouldn't have to install to run tests.
install(
DIRECTORY ${bt_SRC}/
DESTINATION ${INSTALL_DIR_SUFFIX}/tests/ctest/${bt_DEST}
)
endif()
endfunction() # pxr_install_test_dir
function(pxr_register_test TEST_NAME)
if (BUILD_TESTS)
cmake_parse_arguments(bt
"RUN_SERIAL;PYTHON;REQUIRES_SHARED_LIBS;REQUIRES_PYTHON_MODULES"
"CUSTOM_PYTHON;COMMAND;STDOUT_REDIRECT;STDERR_REDIRECT;DIFF_COMPARE;POST_COMMAND;POST_COMMAND_STDOUT_REDIRECT;POST_COMMAND_STDERR_REDIRECT;PRE_COMMAND;PRE_COMMAND_STDOUT_REDIRECT;PRE_COMMAND_STDERR_REDIRECT;FILES_EXIST;FILES_DONT_EXIST;CLEAN_OUTPUT;EXPECTED_RETURN_CODE;TESTENV"
"ENV;PRE_PATH;POST_PATH;WIN_DLL_PATH"
${ARGN}
)
# Discard tests that required shared libraries.
if(NOT TARGET shared_libs)
# Explicit requirement. This is for C++ tests that dynamically
# load libraries linked against USD code. These tests will have
# multiple copies of symbols and will likely re-execute
# ARCH_CONSTRUCTOR and registration functions, which will almost
# certainly cause problems.
if(bt_REQUIRES_SHARED_LIBS)
message(STATUS "Skipping test ${TEST_NAME}, shared libraries required")
return()
endif()
endif()
if(NOT TARGET python)
# Implicit requirement. Python modules require shared USD
# libraries. If the test runs python it's certainly going
# to load USD modules. If the test uses C++ to load USD
# modules it tells us via REQUIRES_PYTHON_MODULES.
if(bt_PYTHON OR bt_CUSTOM_PYTHON OR bt_REQUIRES_PYTHON_MODULES)
message(STATUS "Skipping test ${TEST_NAME}, Python modules required")
return()
endif()
endif()
# This harness is a filter which allows us to manipulate the test run,
# e.g. by changing the environment, changing the expected return code, etc.
set(testWrapperCmd ${PROJECT_SOURCE_DIR}/${INSTALL_DIR_SUFFIX}/cmake/macros/testWrapper.py --verbose)
if (bt_STDOUT_REDIRECT)
set(testWrapperCmd ${testWrapperCmd} --stdout-redirect=${bt_STDOUT_REDIRECT})
endif()
if (bt_STDERR_REDIRECT)
set(testWrapperCmd ${testWrapperCmd} --stderr-redirect=${bt_STDERR_REDIRECT})
endif()
if (bt_PRE_COMMAND_STDOUT_REDIRECT)
set(testWrapperCmd ${testWrapperCmd} --pre-command-stdout-redirect=${bt_PRE_COMMAND_STDOUT_REDIRECT})
endif()
if (bt_PRE_COMMAND_STDERR_REDIRECT)
set(testWrapperCmd ${testWrapperCmd} --pre-command-stderr-redirect=${bt_PRE_COMMAND_STDERR_REDIRECT})
endif()
if (bt_POST_COMMAND_STDOUT_REDIRECT)
set(testWrapperCmd ${testWrapperCmd} --post-command-stdout-redirect=${bt_POST_COMMAND_STDOUT_REDIRECT})
endif()
if (bt_POST_COMMAND_STDERR_REDIRECT)
set(testWrapperCmd ${testWrapperCmd} --post-command-stderr-redirect=${bt_POST_COMMAND_STDERR_REDIRECT})
endif()
# Not all tests will have testenvs, but if they do let the wrapper know so
# it can copy the testenv contents into the run directory. By default,
# assume the testenv has the same name as the test but allow it to be
# overridden by specifying TESTENV.
if (bt_TESTENV)
set(testenvDir ${PXR_INSTALL_PREFIX}/tests/ctest/${bt_TESTENV})
else()
set(testenvDir ${PXR_INSTALL_PREFIX}/tests/ctest/${TEST_NAME})
endif()
set(testWrapperCmd ${testWrapperCmd} --testenv-dir=${testenvDir})
if (bt_DIFF_COMPARE)
set(testWrapperCmd ${testWrapperCmd} --diff-compare=${bt_DIFF_COMPARE})
# For now the baseline directory is assumed by convention from the test
# name. There may eventually be cases where we'd want to specify it by
# an argument though.
set(baselineDir ${testenvDir}/baseline)
set(testWrapperCmd ${testWrapperCmd} --baseline-dir=${baselineDir})
endif()
if (bt_CLEAN_OUTPUT)
set(testWrapperCmd ${testWrapperCmd} --clean-output-paths=${bt_CLEAN_OUTPUT})
endif()
if (bt_FILES_EXIST)
set(testWrapperCmd ${testWrapperCmd} --files-exist=${bt_FILES_EXIST})
endif()
if (bt_FILES_DONT_EXIST)
set(testWrapperCmd ${testWrapperCmd} --files-dont-exist=${bt_FILES_DONT_EXIST})
endif()
if (bt_PRE_COMMAND)
set(testWrapperCmd ${testWrapperCmd} --pre-command=${bt_PRE_COMMAND})
endif()
if (bt_POST_COMMAND)
set(testWrapperCmd ${testWrapperCmd} --post-command=${bt_POST_COMMAND})
endif()
if (bt_EXPECTED_RETURN_CODE)
set(testWrapperCmd ${testWrapperCmd} --expected-return-code=${bt_EXPECTED_RETURN_CODE})
endif()
if (bt_ENV)
foreach(env ${bt_ENV})
set(testWrapperCmd ${testWrapperCmd} --env-var=${env})
endforeach()
endif()
if (bt_PRE_PATH)
foreach(path ${bt_PRE_PATH})
set(testWrapperCmd ${testWrapperCmd} --pre-path=${path})
endforeach()
endif()
if (bt_POST_PATH)
foreach(path ${bt_POST_PATH})
set(testWrapperCmd ${testWrapperCmd} --post-path=${path})
endforeach()
endif()
if(WIN32)
if (bt_WIN_DLL_PATH)
foreach(path ${bt_WIN_DLL_PATH})
set(testWrapperCmd ${testWrapperCmd} --win-dll-path=${path})
endforeach()
endif()
endif()
# Look for resource files in the "usd" subdirectory relative to the
# "lib" directory where the libraries are installed.
#
# We don't want to copy these resource files for each test, so instead
# we set the PXR_PLUGINPATH_NAME env var to point to the "lib/usd"
# directory where these files are installed.
set(_testPluginPath "${PXR_INSTALL_PREFIX}/maya/plugin;${CMAKE_INSTALL_PREFIX}/lib/usd")
set(_testPrePath "$ENV{PATH};${PXR_INSTALL_PREFIX}/maya/lib;${CMAKE_INSTALL_PREFIX}/lib")
# Ensure that Python imports the Python files built by this build.
# On Windows convert backslash to slash and don't change semicolons
# to colons.
set(_testPythonPath "${CMAKE_INSTALL_PREFIX}/lib/python;${PXR_INSTALL_PREFIX}/lib/python;$ENV{PYTHONPATH}")
if(WIN32)
string(REGEX REPLACE "\\\\" "/" _testPythonPath "${_testPythonPath}")
string(REGEX REPLACE "\\\\" "/" _testPluginPath "${_testPluginPath}")
string(REGEX REPLACE "\\\\" "/" _testPrePath "${_testPrePath}")
else()
string(REPLACE ";" ":" _testPythonPath "${_testPythonPath}")
string(REPLACE ";" ":" _testPluginPath "${_testPluginPath}")
string(REPLACE ";" ":" _testPrePath "${_testPrePath}")
endif()
# Ensure we run with the appropriate python executable.
if (bt_CUSTOM_PYTHON)
set(testCmd "${bt_CUSTOM_PYTHON} ${bt_COMMAND}")
elseif (bt_PYTHON)
set(testCmd "${Python_EXECUTABLE} ${bt_COMMAND}")
else()
set(testCmd "${bt_COMMAND}")
endif()
add_test(
NAME ${TEST_NAME}
COMMAND ${Python_EXECUTABLE} ${testWrapperCmd}
"--env-var=PYTHONPATH=${_testPythonPath}"
"--env-var=${PXR_OVERRIDE_PLUGINPATH_NAME}=${_testPluginPath}"
"--pre-path=${_testPrePath}" ${testCmd}
)
# Set a temporary folder path for the test
# Note: replace bad chars in test_name with _.
string(REGEX REPLACE "[:<>\|]" "_" SANITIZED_TEST_NAME ${TEST_NAME})
set(TEST_TEMP_DIR "${CMAKE_BINARY_DIR}/test/Temporary/${SANITIZED_TEST_NAME}")
set_property(TEST "${TEST_NAME}" APPEND PROPERTY ENVIRONMENT
"TMP=${TEST_TEMP_DIR}"
"TEMP=${TEST_TEMP_DIR}")
file(MAKE_DIRECTORY ${TEST_TEMP_DIR})
# But in some cases, we need to pass cmake properties directly to cmake
# run_test, rather than configuring the environment
if (bt_RUN_SERIAL)
set_tests_properties(${TEST_NAME} PROPERTIES RUN_SERIAL TRUE)
endif()
endif()
endfunction() # pxr_register_test
function(pxr_setup_plugins)
# Install a top-level plugInfo.json in the shared area and into the
# top-level plugin area
_get_resources_dir_name(resourcesDir)
# Add extra plugInfo.json include paths to the top-level plugInfo.json,
# relative to that top-level file.
set(extraIncludes "")
list(REMOVE_DUPLICATES PXR_EXTRA_PLUGINS)
foreach(dirName ${PXR_EXTRA_PLUGINS})
file(RELATIVE_PATH
relDirName
"${CMAKE_INSTALL_PREFIX}/lib/usd"
"${CMAKE_INSTALL_PREFIX}/${dirName}"
)
set(extraIncludes "${extraIncludes},\n \"${relDirName}/\"")
endforeach()
set(plugInfoContents "{\n \"Includes\": [\n \"*/${resourcesDir}/\"${extraIncludes}\n ]\n}\n")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/plugins_plugInfo.json"
"${plugInfoContents}")
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/plugins_plugInfo.json"
DESTINATION ${INSTALL_DIR_SUFFIX}/lib/usd
RENAME "plugInfo.json"
)
set(plugInfoContents "{\n \"Includes\": [ \"*/${resourcesDir}/\" ]\n}\n")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/usd_plugInfo.json"
"${plugInfoContents}")
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/usd_plugInfo.json"
DESTINATION ${INSTALL_DIR_SUFFIX}/plugin/usd
RENAME "plugInfo.json"
)
endfunction() # pxr_setup_plugins
function(pxr_add_extra_plugins PLUGIN_AREAS)
# Install a top-level plugInfo.json in the given plugin areas.
_get_resources_dir_name(resourcesDir)
set(plugInfoContents "{\n \"Includes\": [ \"*/${resourcesDir}/\" ]\n}\n")
get_property(help CACHE PXR_EXTRA_PLUGINS PROPERTY HELPSTRING)
foreach(area ${PLUGIN_AREAS})
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${area}_plugInfo.json"
"${plugInfoContents}")
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/${area}_plugInfo.json"
DESTINATION "${INSTALL_DIR_SUFFIX}/${PXR_INSTALL_SUBDIR}/${area}"
RENAME "plugInfo.json"
)
list(APPEND PXR_EXTRA_PLUGINS "${PXR_INSTALL_SUBDIR}/${area}")
endforeach()
set(PXR_EXTRA_PLUGINS "${PXR_EXTRA_PLUGINS}" CACHE INTERNAL "${help}")
endfunction() # pxr_setup_third_plugins
function(pxr_toplevel_prologue)
# Create a target for shared libraries. We currently use this only
# to test its existence.
if(BUILD_SHARED_LIBS)
add_custom_target(shared_libs)
endif()
# Create a target for targets that require Python. Each should add
# itself as a dependency to the "python" target.
if(TARGET shared_libs)
add_custom_target(python ALL)
endif()
endfunction() # pxr_toplevel_prologue
function(pxr_toplevel_epilogue)
# Setup the plugins in the top epilogue to ensure that everybody has had a
# chance to update PXR_EXTRA_PLUGINS with their plugin paths.
pxr_setup_plugins()
endfunction() # pxr_toplevel_epilogue