Skip to content

Commit

Permalink
Make PackageCompiler.jl compilation selectable in cmake (#128)
Browse files Browse the repository at this point in the history
* give path to init.c depending on build.jl path

* introduce option to use PackageCompiler

- required JULIA_PROJECT_PATH (so does testing)
- install missing
- examples missing

* copy init.c to build tree

s.t. no init.o will end up in the source tree

* rename JULIA_PROJECT_PATH to LIBTRIXI_JULIA_PROJECT

* compile examples when using PackageCompiler

- also add Fortran module

* make installation work when using PackageCompiler

* fix build type in docs

* add libtrixi.so to sources

apparently necessary s.t. a rule for building libtrixi.so is generated

* warn about unsupported testing when using PackageCompiler

* revise cmake script using add_custom_target

* adapt github workflow to use cmake for PackageCompiler.jl

* fix typo

* use absolute path as cmake will change working directory

* fix path for running examples

* Change back `LIBTRIXI_JULIA_PROJECT` --> `JULIA_PROJECT_PATH` 😬

* document usage of PackageCompiler

* use file( COPY ...)

* consistent naming

* Update CMakeLists.txt

* copy file using add_custom_command

this allows to define dependencies

---------

Co-authored-by: Michael Schlottke-Lakemper <michael@sloede.com>
  • Loading branch information
benegee and sloede committed Oct 20, 2023
1 parent 5c9e285 commit d232781
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 93 deletions.
22 changes: 13 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -173,17 +173,21 @@ jobs:
--julia-depot ~/.julia \
--force
- name: Build libtrixi using PackageCompiler
- name: Configure (test_type == 'package-compiler')
if: ${{ matrix.test_type == 'package-compiler' }}
run: |
cd LibTrixi.jl/lib
make
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=../install \
-DCMAKE_BUILD_TYPE=Debug \
-DUSE_PACKAGE_COMPILER=ON \
-DJULIA_PROJECT_PATH=$PWD/../libtrixi-julia
- name: Build example
- name: Build (test_type == 'package-compiler')
if: ${{ matrix.test_type == 'package-compiler' }}
run: |
cd examples
make -f MakefileCompiled LIBTRIXI_PREFIX=$PWD/../LibTrixi.jl/lib/build
cd build
make -j2
- name: Test external CMake project
if: ${{ matrix.test_type == 'regular' }}
Expand Down Expand Up @@ -230,10 +234,10 @@ jobs:
- name: Run examples
if: ${{ matrix.test_type == 'package-compiler' }}
run: |
cd examples
cd build/examples
mpirun -n 2 simple_trixi_controller_c \
../libtrixi-julia \
../LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl
../../libtrixi-julia \
../../LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl
env:
LIBTRIXI_DEBUG: all

Expand Down
155 changes: 106 additions & 49 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,78 +56,135 @@ if( ENABLE_TESTING )
find_package( GTest REQUIRED )

set ( TEST_DRIVE_FIND_METHOD fetch )
# option TEST_DRIVE_BUILD_TESTING is hard-coded to ON
# Option TEST_DRIVE_BUILD_TESTING is hard-coded to ON, could be spared
find_package( test-drive REQUIRED )
endif()

# Optionally use PackageCompiler.jl to build standalone libtrixi.so
option( USE_PACKAGE_COMPILER "Build standalone libtrixi.so using PackageCompiler.jl" )

# Fortran mod file location
set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR})

# Library target
add_library ( ${PROJECT_NAME} SHARED
src/api.c
src/api.f90
src/auxiliary.h
src/auxiliary.c
src/trixi.h
)
if( USE_PACKAGE_COMPILER )
if ( NOT DEFINED JULIA_PROJECT_PATH )
message( FATAL_ERROR "JULIA_PROJECT_PATH needs to be set for PackageCompiler.jl.")
endif()
if ( ENABLE_TESTING )
message( NOTICE "Testing is not supported when PackageCompiler is used.")
endif()

# Include directories, private
target_include_directories ( ${PROJECT_NAME} PRIVATE src )
# Define PackageCompiler.jl output file
set( PC_LIBTRIXI_SO ${CMAKE_BINARY_DIR}/prefix-pc/lib/libtrixi.so )

# Define PackageCompiler.jl initialization source file
set( PC_INIT_SOURCE ${CMAKE_SOURCE_DIR}/LibTrixi.jl/lib/init.c )
set( PC_INIT_BUILD ${CMAKE_BINARY_DIR}/build-pc/init.c )

# Copy initialization source to build directory
add_custom_command( OUTPUT ${PC_INIT_BUILD}
COMMENT "Copying `init.c` to build folder..."
COMMAND ${CMAKE_COMMAND} -E copy ${PC_INIT_SOURCE} ${PC_INIT_BUILD}
DEPENDS ${PC_INIT_SOURCE} )

# Add a library target (libtrixi), only for Fortran module
add_library( ${PROJECT_NAME} OBJECT
src/api.f90
)

# Custom command to run PackageCompiler.jl to produce libtrixi.so
add_custom_command( OUTPUT ${PC_LIBTRIXI_SO}
COMMENT "Building ${PROJECT_NAME} with PackageCompiler.jl..."
COMMAND ${JULIA_EXECUTABLE}
--project=${CMAKE_SOURCE_DIR}/LibTrixi.jl/lib
${CMAKE_SOURCE_DIR}/LibTrixi.jl/lib/build.jl
${JULIA_PROJECT_PATH}
${CMAKE_BINARY_DIR}/prefix-pc
DEPENDS ${PC_INIT_BUILD}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/build-pc )

# Custom target for PackageCompiler.jl's libtrixi.so
add_custom_target( PC_LIBTRIXI DEPENDS ${PC_LIBTRIXI_SO} )

# Dependency of main library target on PackageCompiler.jl target
add_dependencies( ${PROJECT_NAME} PC_LIBTRIXI )

# Add linking to PackageCompiler.jl's libtrixi.so
target_link_libraries( ${PROJECT_NAME} INTERFACE ${PC_LIBTRIXI_SO} )

# Install configuration
install( DIRECTORY "${CMAKE_BINARY_DIR}/prefix-pc/lib/" TYPE LIB )
install( DIRECTORY "${CMAKE_BINARY_DIR}/prefix-pc/share/julia"
DESTINATION share )
else()
# Library target
add_library ( ${PROJECT_NAME} SHARED
src/api.c
src/api.f90
src/auxiliary.h
src/auxiliary.c
src/trixi.h
)

# Version info
set_target_properties ( ${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} )
# Include directories, private
target_include_directories ( ${PROJECT_NAME} PRIVATE src )

# Version info for the shared object
set_target_properties ( ${PROJECT_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR} )
# Version info
set_target_properties ( ${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} )

# Include directories, public for actual users
set_target_properties ( ${PROJECT_NAME} PROPERTIES PUBLIC_HEADER src/trixi.h )
# Version info for the shared object
set_target_properties ( ${PROJECT_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR} )

# Fortran mod file location
set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR})


# Include directories
target_include_directories( ${PROJECT_NAME} PRIVATE src ${JULIA_INCLUDE_DIRS} )
if ( T8CODE_FOUND )
target_include_directories( ${PROJECT_NAME} PRIVATE ${T8CODE_INCLUDE_DIR} )
endif()

# Include directories
target_include_directories( ${PROJECT_NAME} PRIVATE src ${JULIA_INCLUDE_DIRS} )
if ( T8CODE_FOUND )
target_include_directories( ${PROJECT_NAME} PRIVATE ${T8CODE_INCLUDE_DIR} )
endif()
# Libraries to link
target_link_libraries( ${PROJECT_NAME} PRIVATE ${JULIA_LIBRARY} )

# Libraries to link
target_link_libraries( ${PROJECT_NAME} PRIVATE ${JULIA_LIBRARY} )
# Set appropriate compile flags
target_compile_options( ${PROJECT_NAME} PUBLIC "-fPIC" )
target_compile_options( ${PROJECT_NAME} PRIVATE -Wall -Wextra -Werror)
# Require C11 standard with GNU extensions for C files
target_compile_options( ${PROJECT_NAME} PRIVATE $<$<COMPILE_LANGUAGE:C>:-std=gnu11>)
# Require Fortran 2018 standard for Fortran files
target_compile_options( ${PROJECT_NAME} PRIVATE $<$<COMPILE_LANGUAGE:Fortran>:-std=f2018>)

# Set appropriate compile flags
target_compile_options( ${PROJECT_NAME} PUBLIC "-fPIC" )
target_compile_options( ${PROJECT_NAME} PRIVATE -Wall -Wextra -Werror)
# Require C11 standard with GNU extensions for C files
target_compile_options( ${PROJECT_NAME} PRIVATE $<$<COMPILE_LANGUAGE:C>:-std=gnu11>)
# Require Fortran 2018 standard for Fortran files
target_compile_options( ${PROJECT_NAME} PRIVATE $<$<COMPILE_LANGUAGE:Fortran>:-std=f2018>)


# Add auxiliary *object* library to support fast thread-local storage (TLS)
add_library ( ${PROJECT_NAME}_tls OBJECT
src/tls.c
)
target_include_directories( ${PROJECT_NAME}_tls PRIVATE ${JULIA_INCLUDE_DIRS} )

# Add auxiliary *object* library to support fast thread-local storage (TLS)
add_library ( ${PROJECT_NAME}_tls OBJECT
src/tls.c
)
target_include_directories( ${PROJECT_NAME}_tls PRIVATE ${JULIA_INCLUDE_DIRS} )
# Add test on demand
if( ENABLE_TESTING )
enable_testing()
add_subdirectory( test/c )
add_subdirectory( test/fortran )
endif()

# Add examples
add_subdirectory( examples )

# Add test on demand
if( ENABLE_TESTING )
enable_testing()
add_subdirectory( test/c )
add_subdirectory( test/fortran )
# Install configuration
install( FILES $<TARGET_OBJECTS:${PROJECT_NAME}_tls> TYPE LIB RENAME lib${PROJECT_NAME}_tls.o )
install( FILES "${CMAKE_BINARY_DIR}/LIBTRIXI_VERSION" DESTINATION share/julia )
endif()


# Install configuration

# Public header for libtrixi
set_target_properties ( ${PROJECT_NAME} PROPERTIES PUBLIC_HEADER src/trixi.h )

# Common install configuration
install( TARGETS ${PROJECT_NAME} )
install( DIRECTORY LibTrixi.jl DESTINATION share/libtrixi PATTERN "lib" EXCLUDE )
install( FILES ${CMAKE_Fortran_MODULE_DIRECTORY}/libtrixi.mod TYPE INCLUDE)
install( FILES $<TARGET_OBJECTS:${PROJECT_NAME}_tls> TYPE LIB RENAME lib${PROJECT_NAME}_tls.o )
install( DIRECTORY LibTrixi.jl DESTINATION share/libtrixi )
install( FILES "${CMAKE_BINARY_DIR}/LIBTRIXI_VERSION" DESTINATION share/julia )
install( PROGRAMS utils/libtrixi-init-julia TYPE BIN )

# Add examples
add_subdirectory( examples )
46 changes: 28 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ For building, `cmake` and its typical workflow is used.
2. Call cmake

```bash
cmake -DCMAKE_BUILD_TYPE=(debug|release) -DCMAKE_INSTALL_PREFIX=<install_directory> ..
cmake -DCMAKE_BUILD_TYPE=(Debug|Release) -DCMAKE_INSTALL_PREFIX=<install_directory> ..
```

`cmake` should find `MPI` and `Julia` automatically. If not, the directories
Expand Down Expand Up @@ -276,23 +276,33 @@ library with a C interface. This is possible with the use of the Julia package
[PackageCompiler.jl](https://github.com/JuliaLang/PackageCompiler.jl).

To try this out, perform the following steps:
1. Initialize the project directory `libtrixi-julia` using `libtrixi-init-julia` as
described above.
2. Go to the `LibTrixi.jl/lib` directory in the repository root,
make sure that `PROJECT_DIR` (defined in `Makefile`) points to your `libtrixi-julia` directory,
and call `make`:
```shell
cd LibTrixi.jl/lib
make
```
3. Go to the `examples` folder in the repository root and compile
`simple_trixi_controller_c`:
```shell
cd examples
make -f MakefileCompiled LIBTRIXI_PREFIX=$PWD/../LibTrixi.jl/lib/build
```
This will create a `simple_trixi_controller_c` file.
4. From inside the `examples` folder you should be able to run the example (in parallel)
1. Initialize the project directory `libtrixi-julia` using `libtrixi-init-julia` as
described above.
2. Build

*using make*
- Go to the `LibTrixi.jl/lib` directory in the repository root,
make sure that `PROJECT_DIR` (defined in `Makefile`) points to your `libtrixi-julia` directory,
and call `make`:
```shell
cd LibTrixi.jl/lib
make
```
- Go to the `examples` folder in the repository root and compile
`simple_trixi_controller_c`:
```shell
cd examples
make -f MakefileCompiled LIBTRIXI_PREFIX=$PWD/../LibTrixi.jl/lib/build
```
This will create a `simple_trixi_controller_c` file.

*using cmake*
- Add
```
-DUSE_PACKAGE_COMPILER=ON -DJULIA_PROJECT_PATH=<libtrixi-julia_directory>
```
to your cmake call (see above)
3. From inside the `examples` folder you should be able to run the example (in parallel)
with the following command:
```shell
mpirun -n 2 simple_trixi_controller_c \
Expand Down
42 changes: 26 additions & 16 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ For building, `cmake` and its typical workflow is used.
2. Call cmake

```bash
cmake -DCMAKE_BUILD_TYPE=(debug|release) -DCMAKE_INSTALL_PREFIX=<install_directory> ..
cmake -DCMAKE_BUILD_TYPE=(Debug|Release) -DCMAKE_INSTALL_PREFIX=<install_directory> ..
```

`cmake` should find `MPI` and `Julia` automatically. If not, the directories
Expand Down Expand Up @@ -278,21 +278,31 @@ library with a C interface. This is possible with the use of the Julia package
To try this out, perform the following steps:
1. Initialize the project directory `libtrixi-julia` using `libtrixi-init-julia` as
described above.
2. Go to the `LibTrixi.jl/lib` directory in the repository root,
make sure that `PROJECT_DIR` (defined in `Makefile`) point to your `libtrixi-julia` directory,
and call `make`:
```shell
cd LibTrixi.jl/lib
make
```
3. Go to the `examples` folder in the repository root and compile
`simple_trixi_controller_c`:
```shell
cd examples
make -f MakefileCompiled LIBTRIXI_PREFIX=$PWD/../LibTrixi.jl/lib/build
```
This will create a `simple_trixi_controller_c` file.
4. From inside the `examples` folder you should be able to run the example (in parallel)
2. Build

*using make*
- Go to the `LibTrixi.jl/lib` directory in the repository root,
make sure that `PROJECT_DIR` (defined in `Makefile`) points to your `libtrixi-julia` directory,
and call `make`:
```shell
cd LibTrixi.jl/lib
make
```
- Go to the `examples` folder in the repository root and compile
`simple_trixi_controller_c`:
```shell
cd examples
make -f MakefileCompiled LIBTRIXI_PREFIX=$PWD/../LibTrixi.jl/lib/build
```
This will create a `simple_trixi_controller_c` file.

*using cmake*
- Add
```
-DUSE_PACKAGE_COMPILER=ON -DJULIA_PROJECT_PATH=<libtrixi-julia_directory>
```
to your cmake call (see above)
3. From inside the `examples` folder you should be able to run the example (in parallel)
with the following command:
```shell
mpirun -n 2 simple_trixi_controller_c \
Expand Down
8 changes: 7 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ foreach ( EXAMPLE ${EXAMPLES} )
# set libraries to link
target_link_libraries(
${TARGET_NAME}
PRIVATE MPI::MPI_${EXAMPLE_LANG} ${PROJECT_NAME} ${PROJECT_NAME}_tls
PRIVATE MPI::MPI_${EXAMPLE_LANG} ${PROJECT_NAME}
)
if ( NOT USE_PACKAGE_COMPILER )
target_link_libraries( ${TARGET_NAME} PRIVATE ${PROJECT_NAME}_tls )
endif()
if ( T8CODE_FOUND )
target_link_libraries( ${TARGET_NAME} PRIVATE ${T8CODE_LIBRARIES} )
endif()
Expand All @@ -52,6 +55,9 @@ foreach ( EXAMPLE ${EXAMPLES} )
PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib"
)

# position independent code
target_compile_options( ${TARGET_NAME} PRIVATE "-fPIC" )

# enable warnings
target_compile_options( ${TARGET_NAME} PRIVATE -Wall -Wextra -Werror )

Expand Down

0 comments on commit d232781

Please sign in to comment.