Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions doc/rst/usingchapel/compiling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,16 @@ code:
add_executable(myChapelProgram main.chpl)
target_link_options(main PRIVATE -I${CMAKE_SOURCE_DIR}/include)
target_link_libraries(myChapelProgram PRIVATE myCCode)

To enable use of CMake-based projects with the :ref:`language server <readme-chpl-language-server>`,
the CMake integration provides a special variable ``CMAKE_EXPORT_CHPL_COMMANDS``.
When set to ``ON``, CMake will generate a file named ``.cls_commands.json`` in
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs updates too :)

the build directory. This file can be read by the language server to understand
the module structure of the project. For example:

.. code-block:: sh

mkdir build && cd build
cmake .. -CMAKE_EXPORT_CHPL_COMMANDS=ON
cmake --build .
cd .. && ln -s build/.cls-commands.json .cls-commands.json
47 changes: 38 additions & 9 deletions tools/chpl-language-server/src/chpl-shim.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,22 +64,25 @@ def run_toplevel():
# TODO: this only works when chpl is not passed as a path and we rely on
# the PATH to find it. i.e. `./bin/chpl-shim ./bin/chpl` will not work.

newenv = os.environ.copy()

# Create a temporary directory to add the 'chpl' wrapper script
tempdir = tempfile.TemporaryDirectory()
wrapper = os.path.join(tempdir.name, "chpl")
os.symlink(__file__, wrapper)

if "CHPL_SHIM_TARGET_PATH" not in newenv:
newenv["CHPL_SHIM_TARGET_PATH"] = tempdir.name
if "CHPL_SHIM_REAL_COMPILER_PATH" not in newenv:
chpl = (
subprocess.check_output(["which", "chpl"])
.decode(sys.stdout.encoding)
.strip()
)
newenv["CHPL_SHIM_REAL_COMPILER_PATH"] = chpl

# Modify path to include the wrapper script at the front
chpl = (
subprocess.check_output(["which", "chpl"])
.decode(sys.stdout.encoding)
.strip()
)
newpath = os.pathsep.join([tempdir.name, os.environ["PATH"]])

newenv = os.environ.copy()
newenv["CHPL_SHIM_TARGET_PATH"] = tempdir.name
newenv["CHPL_SHIM_REAL_COMPILER_PATH"] = chpl
newenv["PATH"] = newpath

# Invoke the script I was asked to invoke
Expand Down Expand Up @@ -204,6 +207,16 @@ def run_chpl_shim():
files += list_parsed_files(files, args.module_dirs)
files = list(set(files))

# Detect symlinks in the form '.chpl.chpl'. These are produced by
# our current CMake support. Instead, resolve the symlink to the real
# file to avoid confusion.
for i in range(len(files)):
file = files[i]
if file.endswith(".chpl.chpl") and os.path.islink(file):
real_file = os.path.realpath(file)
assert real_file.endswith(".chpl")
files[i] = real_file

commands = {}
invocation = " ".join(sys.argv).replace(__file__, real_compiler)
commands["invocation"] = invocation
Expand All @@ -227,6 +240,22 @@ def run_chpl_shim():


if __name__ == "__main__":
"""
The normal flow is as follows:
1. The shim is invoked as the driver, where the rest of the arguments
are the command that ends up building a Chapel program.
2. Assuming that the comamnd refers to "just" 'chpl' (i.e. not a path to chpl),
the shim creates a temporary directory, links itself as 'chpl' in that directory,
and modifies the PATH to include that directory at the front.
This way, when the command invokes 'chpl', it will invoke the shim again,
but this time as the wrapper.
3. When this happens, the shim receives all the arguments the command
would've provided to the real 'chpl' compiler. The shim then extracts
the .chpl files and other data needed for .cls-commands.json, writes
that data to a temporary file, and then invokes the real 'chpl'
compiler with the same arguments it received.
"""

if sys.argv[0].endswith("chpl-shim.py"):
run_toplevel()
else:
Expand Down
21 changes: 20 additions & 1 deletion util/cmake/CMakeCHPLInformation.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,26 @@
# TODO: this is a hack, how do we tell cmake that we can't compile to object files?
# TODO: how do we respect <DEFINES> and <INCLUDES>, CMake will only fill that in for CMAKE_*_COMPILER_OBJECT
set(CMAKE_CHPL_COMPILE_OBJECT "test -f <OBJECT> || ln -s <SOURCE> <OBJECT>")
set(CMAKE_CHPL_LINK_EXECUTABLE "<CMAKE_CHPL_COMPILER> -o <TARGET> <OBJECTS> <FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>")

# Support for CMAKE_EXPORT_CHPL_COMMANDS (similar to CMAKE_EXPORT_COMPILE_COMMANDS)
set(CHPL_COMPILER_FLAGS "-o <TARGET> <OBJECTS> <FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>")
set(CMAKE_CHPL_LINK_EXECUTABLE "<CMAKE_CHPL_COMPILER> ${CHPL_COMPILER_FLAGS}")
if(CMAKE_EXPORT_CHPL_COMMANDS)
# Get the directory containing the chpl compiler to find chpl-shim
get_filename_component(CHPL_BIN_DIR "${CMAKE_CHPL_COMPILER}" DIRECTORY)
set(CHPL_SHIM_SCRIPT "${CHPL_BIN_DIR}/chpl-shim")

message(STATUS "CMAKE_EXPORT_CHPL_COMMANDS is ON, checking for chpl-shim at ${CHPL_SHIM_SCRIPT}")

if(EXISTS "${CHPL_SHIM_SCRIPT}")
# Use chpl-shim as a wrapper to generate .cls-commands.json
# Note: chpl-shim expects to be called as 'chpl-shim chpl <args>', not with full path
Comment on lines +34 to +35
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😭

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels like that's a hard limitation without dynamic loading magic (whatever bear does)

message(STATUS "Found chpl-shim. Configuring build command to use chpl-shim to generate .cls-commands.json")
set(CMAKE_CHPL_LINK_EXECUTABLE "<CMAKE_COMMAND> -E env CHPL_SHIM_REAL_COMPILER_PATH=${CMAKE_CHPL_COMPILER} ${CHPL_SHIM_SCRIPT} chpl ${CHPL_COMPILER_FLAGS}")
else()
message(WARNING "CMAKE_EXPORT_CHPL_COMMANDS is set but chpl-shim not found at ${CHPL_SHIM_SCRIPT}")
endif()
endif()

# TODO: support --library directly to build Chapel shared libs for interoperability
# CMAKE_*_CREATE_SHARED_LIBRARY
Expand Down
10 changes: 10 additions & 0 deletions util/cmake/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,13 @@ project(hello LANGUAGES CHPL)
add_executable(hello hello.chpl)
```

## Language Server Integration

To enable Chapel Language Server integration, set `CMAKE_EXPORT_CHPL_COMMANDS` to `ON`:

```cmake
set(CMAKE_EXPORT_CHPL_COMMANDS ON)
```

This will generate a `.cls-commands.json` file in your build directory that the Chapel Language Server can use to understand your project's module paths and source files.