Skip to content

Commit 51d56b8

Browse files
authored
Added better distro support (MacOS and FreeBSD) (#21)
* Added better support for MacOS Brew environment (finding lib paths) * Added better support for non-Debian distros (finding lib paths) * Added MacOS testing workflow * Switched to `uv` for environment setup and explicit installation of dependencies * Added better dependency documentation to readme
1 parent 364ae73 commit 51d56b8

9 files changed

+213
-78
lines changed

.github/workflows/test.macos.yml

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Test MacOS
2+
3+
on:
4+
push:
5+
branches:
6+
- '**'
7+
pull_request:
8+
branches: [ main ]
9+
10+
jobs:
11+
12+
test:
13+
name: Testing ${{matrix.os}} py-${{matrix.python-version}}
14+
runs-on: ${{matrix.os}}
15+
16+
strategy:
17+
matrix:
18+
os: ['macos-latest']
19+
python-version: ['3.11', '3.12']
20+
21+
steps:
22+
- uses: actions/checkout@v2
23+
24+
- name: Install the latest version of uv
25+
uses: astral-sh/setup-uv@v5
26+
27+
- run: which brew
28+
- run: brew install gcc openblas lapack libomp
29+
- run: ls /opt/homebrew/bin/
30+
- run: which gfortran-14
31+
32+
- run: FC=gfortran-14 make env_uv python_version=${{ matrix.python-version }}
33+
34+
- run: make test
35+
- run: make format
36+
- run: FC=gfortran-14 make build
37+
- run: make test-dist

.github/workflows/test.ubuntu.yml

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: Test Ubuntu
2+
3+
on:
4+
push:
5+
branches:
6+
- '**'
7+
pull_request:
8+
branches: [ main ]
9+
10+
jobs:
11+
12+
test:
13+
name: Testing ${{matrix.os}} py-${{matrix.python-version}}
14+
runs-on: ${{matrix.os}}
15+
16+
strategy:
17+
matrix:
18+
os: ['ubuntu-latest']
19+
python-version: ['3.11', '3.12']
20+
21+
steps:
22+
- uses: actions/checkout@v2
23+
24+
- name: Install the latest version of uv
25+
uses: astral-sh/setup-uv@v5
26+
27+
- run: sudo apt-get install -y gcc libomp-dev libopenblas-dev
28+
29+
- run: make env_uv python_version=${{ matrix.python-version }}
30+
31+
- run: make test
32+
- run: make format
33+
- run: make build
34+
- run: make test-dist

.github/workflows/test.yml

-32
This file was deleted.

Makefile

+18-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
python=./env/bin/python
2-
mamba=mamba
1+
env=env
2+
python=./${env}/bin/python
3+
python_version=3.12
4+
conda=mamba
35
pkg=qmllib
46
pip=./env/bin/pip
57
pytest=pytest
@@ -9,14 +11,25 @@ version_file=src/qmllib/version.py
911

1012
.PHONY: build
1113

12-
all: env
14+
all: ${env}
1315

1416
## Setup
1517

1618
env:
17-
${mamba} env create -f ./environment_dev.yaml -p ./env --quiet
18-
${python} -m pre_commit install
19+
echo "TODO"
20+
21+
env_uv:
22+
which uv
23+
uv venv ${env} --python ${python_version}
24+
uv pip install -r requirements.txt --python ${python}
25+
uv pip install -e . --python ${python}
26+
make .git/hooks/pre-commit python=${python}
27+
28+
env_conda:
29+
which ${conda}
30+
${conda} env create -f ./environment.yaml -p ./${env} --quiet
1931
${python} -m pip install -e .
32+
make .git/hooks/pre-commit python=${python}
2033

2134
./.git/hooks/pre-commit:
2235
${python} -m pre_commit install

README.rst

+8-3
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,19 @@ and function naming.
2828
How to install
2929
==============
3030

31-
You need a fortran compiler and math library. Default is `gfortran` and `openblas`.
31+
You need a fortran compiler, OpenMP and a math library. Default is `gfortran` and `openblas`.
3232

33+
.. code-block:: bash
34+
35+
sudo apt install gcc libomp-dev libopenblas-dev
36+
37+
If you are on mac, you can install `gcc`, OpenML and BLAS/Lapack via `brew`
3338

3439
.. code-block:: bash
3540
36-
sudo apt install libopenblas-dev gcc
41+
brew install gcc libomp openblas lapack
3742
38-
You can install it via PyPi
43+
You can then install via PyPi
3944

4045
.. code-block:: bash
4146

_compile.py

+90-13
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
import numpy as np
99

10+
DEFAULT_FC = "gfortran"
11+
1012
f90_modules = {
1113
"representations/frepresentations": ["frepresentations.f90"],
1214
"representations/facsf": ["facsf.f90"],
@@ -38,41 +40,116 @@ def find_mkl():
3840

3941

4042
def find_env() -> dict[str, str]:
41-
"""Find compiler flags"""
43+
"""Find compiler flag"""
44+
45+
"""
46+
For anaconda-like envs
47+
TODO Find MKL
48+
49+
For brew,
50+
51+
brew install llvm libomp
52+
brew install openblas lapack
53+
54+
export LDFLAGS="-L/opt/homebrew/opt/lapack/lib"
55+
export CPPFLAGS="-I/opt/homebrew/opt/lapack/include"
56+
export LDFLAGS="-L/opt/homebrew/opt/libomp/lib"
57+
export CPPFLAGS="-I/opt/homebrew/opt/libomp/include"
58+
59+
"""
60+
61+
fc = os.environ.get("FC", DEFAULT_FC)
62+
63+
linker_mathlib_dirs = [
64+
"/usr/lib/", # Debian
65+
"/lib/", # Alpine
66+
"/usr/local/lib/", # FreeBSD
67+
"/usr/lib64/", # Redhat
68+
]
69+
70+
mathlib_path = None
71+
72+
for dir in linker_mathlib_dirs:
73+
74+
if not Path(dir).is_dir():
75+
continue
76+
77+
mathlib_path = dir
78+
break
4279

43-
# TODO Check if FCC is there, not not raise Error
80+
if mathlib_path is None:
81+
print("Unable to find mathlib path")
82+
83+
# TODO Check if FC is there, not not raise Error
4484
# TODO Check if lapack / blas is there, if not raise Error
85+
# TODO Check if omp is installed
86+
87+
# TODO Find ifort flags, choose from FC
88+
# TODO Find mkl lib
4589

46-
# TODO Find ifort flags, choose from FCC
47-
# TODO Find math lib
48-
# TODO Find os
90+
# TODO Check if darwin, check for brew paths
4991

50-
COMPILER_FLAGS = [
92+
# Default GNU flags
93+
compiler_flags = [
5194
"-O3",
52-
"-fopenmp",
5395
"-m64",
5496
"-march=native",
5597
"-fPIC",
5698
"-Wno-maybe-uninitialized",
5799
"-Wno-unused-function",
58100
"-Wno-cpp",
59101
]
102+
compiler_openmp = [
103+
"-fopenmp",
104+
]
105+
linker_flags = [
106+
"-lpthread",
107+
"-lm",
108+
"-ldl",
109+
]
110+
linker_openmp = [
111+
"-lgomp",
112+
]
113+
linker_math = [
114+
"-lblas",
115+
"-llapack",
116+
]
117+
118+
if mathlib_path is not None:
119+
linker_math += [f"-L{mathlib_path}"]
120+
121+
if sys.platform == "darwin":
122+
123+
expected_omp_dir = Path("/opt/homebrew/opt/libomp/lib")
124+
125+
if expected_omp_dir.is_dir():
126+
compiler_openmp = [
127+
"-fopenmp",
128+
]
129+
linker_openmp = [
130+
f"-L{expected_omp_dir}",
131+
"-lomp",
132+
]
60133

61-
extra_flags = ["-lgomp", "-lpthread", "-lm", "-ldl"]
62-
math_flags = ["-L/usr/lib/", "-lblas", "-llapack"]
134+
else:
135+
print(f"Expected OpenMP dir not found: {expected_omp_dir}, compiling without OpenMP")
136+
compiler_openmp = []
137+
linker_openmp = []
63138

64-
fflags = [] + COMPILER_FLAGS
65-
ldflags = [] + extra_flags + math_flags
66-
fcc = "gfortran"
139+
fflags = [] + compiler_flags + compiler_openmp
140+
ldflags = [] + linker_flags + linker_math + linker_openmp
67141

68-
env = {"FFLAGS": " ".join(fflags), "LDFLAGS": " ".join(ldflags), "FCC": fcc}
142+
env = {"FFLAGS": " ".join(fflags), "LDFLAGS": " ".join(ldflags), "FC": fc}
69143

70144
return env
71145

72146

73147
def main():
74148
"""Compile f90 in src/qmllib"""
75149

150+
print(
151+
f"Using python {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
152+
)
76153
print(f"Using numpy {np.__version__}")
77154

78155
# Find and set Fortran compiler, compiler flags and linker flags

environment.yaml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name: qmllib_dev
2+
channels:
3+
- conda-forge
4+
- defaults
5+
dependencies:
6+
- python==3.12
7+
- pip
8+
- pip:
9+
- -r ./requirements.txt

environment_dev.yaml

-25
This file was deleted.

requirements.txt

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# dev
2+
jupytext
3+
monkeytype
4+
numpy
5+
pandas
6+
pip
7+
pre-commit
8+
pytest
9+
pytest-cov
10+
scikit-learn
11+
scipy
12+
# build
13+
build
14+
meson
15+
ninja
16+
# publish
17+
twine

0 commit comments

Comments
 (0)