Skip to content

Support linking against external libraries with Chapel's CMake support #27047

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 15, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
38 changes: 38 additions & 0 deletions doc/rst/usingchapel/compiling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,41 @@ will build a release version of the program:
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=release
cmake --build .


Additional compilation flags for compiling the Chapel code can be added using
``target_link_options``. For example, this snippet limits the amount of
optimization done by the backend compiler to speed up compilation times.

.. code-block:: cmake

target_link_options(myProgram PRIVATE --ccflags -O1)

This also means that projects using a mix of C and Chapel code may need to
specify arguments twice. For example, this snippet shows a project that uses
both Chapel and C code:

.. code-block:: cmake

add_executable(main)
target_sources(main PRIVATE myChapelProgram.chpl src/c_source_file.c)
set_target_properties(main PROPERTIES LINKER_LANGUAGE CHPL)

# used by C compiler
target_include_directories(main PRIVATE include)
# used by Chapel compiler
target_link_options(main PRIVATE -I${CMAKE_SOURCE_DIR}/include)


In larger projects, it may be useful to compile the C code separately. This can
be done by creating a library target for the C code and linking it to the Chapel
code:

.. code-block:: cmake

add_library(myCCode src/c_source_file.c)
target_include_directories(myCCode PRIVATE include)

add_executable(myChapelProgram main.chpl)
target_link_options(main PRIVATE -I${CMAKE_SOURCE_DIR}/include)
target_link_libraries(myChapelProgram PRIVATE myCCode)
Empty file added test/cmake/linkWithC.notest
Empty file.
18 changes: 18 additions & 0 deletions test/cmake/linkWithC/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
cmake_minimum_required(VERSION 3.21.1)

find_package(chpl REQUIRED)

project(linkWithC LANGUAGES CHPL C)
message(STATUS "Using chpl: ${CMAKE_CHPL_COMPILER}")


add_executable(main)
target_sources(main PRIVATE main.chpl src/adder.c)
set_target_properties(main PROPERTIES LINKER_LANGUAGE CHPL)

# used by C compiler
target_include_directories(main PRIVATE include)
# used by Chapel compiler
target_link_options(main PRIVATE -I${CMAKE_SOURCE_DIR}/include)

install(TARGETS main DESTINATION ".")
6 changes: 6 additions & 0 deletions test/cmake/linkWithC/include/adder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef MY_ADDER_H
#define MY_ADDER_H

int add(int a, int b);

#endif
7 changes: 7 additions & 0 deletions test/cmake/linkWithC/main.chpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use CTypes;
require "adder.h";
extern proc add(a: c_int, b: c_int): c_int;
proc main() {
writeln("Hello, world!");
writeln("1 + 2 = ", add(1, 2));
}
5 changes: 5 additions & 0 deletions test/cmake/linkWithC/src/adder.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include <adder.h>

int add(int a, int b) {
return a + b;
}
Empty file added test/cmake/sharedLib.notest
Empty file.
19 changes: 19 additions & 0 deletions test/cmake/sharedLib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.21.1)

find_package(chpl REQUIRED)

project(sharedLib LANGUAGES CHPL C)
message(STATUS "Using chpl: ${CMAKE_CHPL_COMPILER}")


add_library(adder SHARED)
target_sources(adder PRIVATE src/adder.c)
target_include_directories(adder PUBLIC include)
install(TARGETS adder DESTINATION "lib")


add_executable(main)
target_sources(main PRIVATE main.chpl)
target_link_libraries(main adder)
target_link_options(main PRIVATE -I${CMAKE_SOURCE_DIR}/include)
install(TARGETS main DESTINATION "bin")
6 changes: 6 additions & 0 deletions test/cmake/sharedLib/include/adder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef MY_ADDER_H
#define MY_ADDER_H

int add(int a, int b);

#endif
8 changes: 8 additions & 0 deletions test/cmake/sharedLib/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include <stdio.h>
#include "adder.h"
int main() {
int a = 1;
int b = 2;
int c = add(a, b);
printf("a + b = %d\n", c);
}
7 changes: 7 additions & 0 deletions test/cmake/sharedLib/main.chpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use CTypes;
require "adder.h";
extern proc add(a: c_int, b: c_int): c_int;
proc main() {
writeln("Hello, world!");
writeln("1 + 2 = ", add(1, 2));
}
5 changes: 5 additions & 0 deletions test/cmake/sharedLib/src/adder.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include <adder.h>

int add(int a, int b) {
return a + b;
}
Empty file added test/cmake/staticLib.notest
Empty file.
19 changes: 19 additions & 0 deletions test/cmake/staticLib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.21.1)

find_package(chpl REQUIRED)

project(staticLib LANGUAGES CHPL C)
message(STATUS "Using chpl: ${CMAKE_CHPL_COMPILER}")


add_library(adder STATIC)
target_sources(adder PRIVATE src/adder.c)
target_include_directories(adder PUBLIC include)
install(TARGETS adder DESTINATION "lib")


add_executable(main)
target_sources(main PRIVATE main.chpl)
target_link_libraries(main adder)
target_link_options(main PRIVATE -I${CMAKE_SOURCE_DIR}/include)
install(TARGETS main DESTINATION "bin")
6 changes: 6 additions & 0 deletions test/cmake/staticLib/include/adder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef MY_ADDER_H
#define MY_ADDER_H

int add(int a, int b);

#endif
7 changes: 7 additions & 0 deletions test/cmake/staticLib/main.chpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use CTypes;
require "adder.h";
extern proc add(a: c_int, b: c_int): c_int;
proc main() {
writeln("Hello, world!");
writeln("1 + 2 = ", add(1, 2));
}
5 changes: 5 additions & 0 deletions test/cmake/staticLib/src/adder.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include <adder.h>

int add(int a, int b) {
return a + b;
}
2 changes: 2 additions & 0 deletions test/cmake/sub_test
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ def run_builds(d):
continue
run_build(subdir, "Debug")
run_build(subdir, "Release")
run_build(subdir, "RelWithDebInfo")
run_build(subdir, "MinSizeRel")


def main():
Expand Down
5 changes: 3 additions & 2 deletions util/cmake/CMakeCHPLInformation.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@


# 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>")
# <COMPILE_FLAGS> doesn't work on link step
set(CMAKE_CHPL_LINK_EXECUTABLE "<CMAKE_CHPL_COMPILER> -o <TARGET> <OBJECTS> <FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>")

# TODO: support --library directly to build Chapel shared libs for interoperability
# CMAKE_*_CREATE_SHARED_LIBRARY

set(CMAKE_CHPL_SOURCE_FILE_EXTENSIONS chpl)

Expand Down