Skip to content

Commit e5eac84

Browse files
[CMake][TableGen] Make TableGen CMake functions compatible with CMP0116
By default, `add_custom_command` rules execute within their defining directory's corresponding build directory. When `DEPFILE` is used with Ninja, this causes a discrepancy: Ninja expects the path in the depfile to be a relative path from the root of the build directory, but since the working directory is changed by default during the execution of the rule, the path won't match up, and Ninja will conservatively ignore the depfile. Historically, this is the only way it worked, and CMakeLists.txt files would have to be written to work around this, manually converting paths to build-root-directory-relative and changing the working directory of the command to match. Starting with CMake 3.20, CMake introduced a native workaround, controlled by policy CMP0116. When CMP0116 is set to NEW, CMake will automatically translate depfiles such that CMakeLists.txt no longer need to be written taking this into account. This behavior is incompatible with the manual workaround. LLVM sets CMP0116 to OLD in `cmake/Modules/CMakePolicy.cmake`, so when building LLVM, this is not a problem -- we turn off CMake's native workaround and work around it ourselves. Since the TableGen CMake modules are also installed along with LLVM, downstream projects that use LLVM and its TableGen CMake rules are also forced to adopt CMP0116 to be set to OLD. This causes conflicts when other dependencies of such downstream projects require CMP0116 to be set to NEW. CMake policy scopes can help with this, but it is tedious to handle, as a policy scope would need to be introduced whenever the TableGen rule is used, and it requires the caller to understand an implementation detail of the TableGen rule. Instead, this PR changes the TableGen CMake rules such that they will inspect the current state of CMP0116, and only conditionally apply the manual workaround. This way, the TableGen rules will work regardless of the setting of CMP0116. In the future, potentially the value of CMP0116 set in `CMakePolicy.cmake` could change to bring LLVM up-to-date with CMake default behavior. However, I am leaving out such a default change to reduce any possibility of breakage for other downstream projects at this time.
1 parent 3dc098d commit e5eac84

File tree

2 files changed

+54
-24
lines changed

2 files changed

+54
-24
lines changed

llvm/cmake/modules/TableGen.cmake

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,34 @@ function(tablegen project ofn)
1919

2020
# Use depfile instead of globbing arbitrary *.td(s) for Ninja.
2121
if(CMAKE_GENERATOR MATCHES "Ninja")
22-
# Make output path relative to build.ninja, assuming located on
23-
# ${CMAKE_BINARY_DIR}.
2422
# CMake emits build targets as relative paths but Ninja doesn't identify
25-
# absolute path (in *.d) as relative path (in build.ninja)
26-
# Note that tblgen is executed on ${CMAKE_BINARY_DIR} as working directory.
27-
file(RELATIVE_PATH ofn_rel
28-
${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${ofn})
29-
set(additional_cmdline
30-
-o ${ofn_rel}
31-
-d ${ofn_rel}.d
32-
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
33-
DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.d
34-
)
23+
# absolute path (in *.d) as relative path (in build.ninja). If CMP0116 is
24+
# NEW, CMake handles this discrepancy for us -- otherwise, we have to work
25+
# around it ourselves.
26+
if(POLICY CMP0116)
27+
cmake_policy(GET CMP0116 cmp0116_state)
28+
else()
29+
set(cmp0116_state OLD)
30+
endif()
31+
if(cmp0116_state STREQUAL NEW)
32+
set(additional_cmdline
33+
-o ${ofn}
34+
-d ${ofn}.d
35+
DEPFILE ${ofn}.d
36+
)
37+
else()
38+
# Make output path relative to build.ninja, assuming located on
39+
# ${CMAKE_BINARY_DIR}.
40+
# Note that tblgen is executed on ${CMAKE_BINARY_DIR} as working directory.
41+
file(RELATIVE_PATH ofn_rel
42+
${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${ofn})
43+
set(additional_cmdline
44+
-o ${ofn_rel}
45+
-d ${ofn_rel}.d
46+
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
47+
DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.d
48+
)
49+
endif()
3550
set(local_tds)
3651
set(global_tds)
3752
else()

mlir/cmake/modules/AddMLIR.cmake

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,34 @@ function(_pdll_tablegen project ofn)
4848

4949
# Use depfile instead of globbing arbitrary *.td(s) for Ninja.
5050
if(CMAKE_GENERATOR MATCHES "Ninja")
51-
# Make output path relative to build.ninja, assuming located on
52-
# ${CMAKE_BINARY_DIR}.
5351
# CMake emits build targets as relative paths but Ninja doesn't identify
54-
# absolute path (in *.d) as relative path (in build.ninja)
55-
# Note that tblgen is executed on ${CMAKE_BINARY_DIR} as working directory.
56-
file(RELATIVE_PATH ofn_rel
57-
${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${ofn})
58-
set(additional_cmdline
59-
-o ${ofn_rel}
60-
-d ${ofn_rel}.d
61-
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
62-
DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.d
63-
)
52+
# absolute path (in *.d) as relative path (in build.ninja). If CMP0116 is
53+
# NEW, CMake handles this discrepancy for us -- otherwise, we have to work
54+
# around it ourselves.
55+
if(POLICY CMP0116)
56+
cmake_policy(GET CMP0116 cmp0116_state)
57+
else()
58+
set(cmp0116_state OLD)
59+
endif()
60+
if(cmp0116_state STREQUAL NEW)
61+
set(additional_cmdline
62+
-o ${ofn}
63+
-d ${ofn}.d
64+
DEPFILE ${ofn}.d
65+
)
66+
else()
67+
# Make output path relative to build.ninja, assuming located on
68+
# ${CMAKE_BINARY_DIR}.
69+
# Note that tblgen is executed on ${CMAKE_BINARY_DIR} as working directory.
70+
file(RELATIVE_PATH ofn_rel
71+
${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${ofn})
72+
set(additional_cmdline
73+
-o ${ofn_rel}
74+
-d ${ofn_rel}.d
75+
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
76+
DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.d
77+
)
78+
endif()
6479
set(local_tds)
6580
set(global_tds)
6681
else()

0 commit comments

Comments
 (0)