-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathsetup.py
More file actions
211 lines (180 loc) · 8.25 KB
/
setup.py
File metadata and controls
211 lines (180 loc) · 8.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
"""
################################################################################
# LICENSE #
################################################################################
# This file is part of rss_ringoccs. #
# #
# rss_ringoccs is free software: you can redistribute it and/or #
# modify it under the terms of the GNU General Public License as published #
# by the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# rss_ringoccs is distributed in the hope that it will be useful #
# but WITHOUT ANY WARRANTY# without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with rss_ringoccs. If not, see <https://www.gnu.org/licenses/>. #
################################################################################
# Purpose: #
# Compiles all of the C code and build the python package rss_ringoccs. #
################################################################################
# DEPENDENCIES #
################################################################################
# 1.) numpy #
# Used for working with homogeneous arrays. #
# 2.) setuptools #
# Replaces distutils since this has been deprecated. #
################################################################################
# Author: Ryan Maguire #
# Date: 2024/09/09 #
################################################################################
"""
import os
import platform
import subprocess
import shutil
# Python is swapping distutils with setuptools.
try:
from setuptools import setup, Extension
except ImportError:
from distutils.core import setup, Extension
# Numpy is needed for the get_include function which tells us where various
# header files, like numpy/arrayobject.h, live.
import numpy
# Check if OpenMP support has been requested.
USE_OPENMP = os.environ.get('USE_OPENMP') == '1'
# This seems to be needed to ensure Python uses the correct gcc. Without this
# You may get a linker warning, for example:
# ld: warning: dylib (/usr/local/lib/librssringoccs.so) was built for
# newer macOS version (10.15) than being linked (10.9)
# librssringoccs is built using a shell script and makes calls to gcc, whereas
# this file is using Python's distutils to handle the compiling. It seems
# Python may use the wrong compiler, causing this error. Setting the following
# CFLAG fixed the issue.
# We only need this fix for macOS, so check what operating system is used.
if platform.system() == "Darwin":
os.environ["CFLAGS"] = f"-mmacosx-version-min={platform.mac_ver()[0]}"
srclist = []
def add_directory(directory):
"""
Function for adding all of the C files in a
given directory to the list of files to be compiled.
"""
full_path = f'rss_ringoccs/crssringoccs/{directory}/'
for file in os.listdir(full_path):
if file[-1] == "c":
srclist.append(f'{full_path}{file}')
def openmp_args():
"""
Returns the list of arguments needed by
the C compiler to enable OpenMP support.
"""
if not USE_OPENMP:
return [], []
# Microsoft's MSVC compiler supports OpenMP 2.0.
if os.name == "nt":
return ["/openmp"], []
# OpenMP support is also possible on macOS (but tricky to set up).
if platform.system() == "Darwin":
# The required flags for Apple's clang and GCC differ.
cc = os.environ.get("CC", "")
# GCC on macOS does not need -Xpreprocessor. Adding it breaks the
# linker when building with OpenMP support.
if "gcc" in cc:
return ["-fopenmp"], ["-fopenmp"]
# Apple's Clang on macOS requires -Xpreprocessor. Omiting results
# in an "unsupported option: -fopenmp" error. We also need to add
# the path to libomp. The user should specify this directly using
# export CPATH="...". Use brew --prefix as a fallback if this is
# not set.
lflag = "-L" + os.environ.get("CPATH", "$(brew --prefix libomp)/lib")
return ["-Xpreprocessor", "-fopenmp"], [lflag, "-lomp"]
# On GNU / Linux, GCC has OpenMP support by default, and LLVM's clang
# has support as well (but you may need to install libomp to use it).
return ["-fopenmp"], ["-fopenmp"]
def static_library_paths():
"""
Generates both librssringoccs.a and libtmpl.a and returns
(rssringoccs.lib and tmpl.lib on Windows), and returns the
paths to these generated files.
"""
# Windows users are required to use CMake. GNU, Linux, FreeBSD, and
# macOS users may also use CMake.
if shutil.which("cmake"):
build_dir = "build"
cmake_args = ["cmake", "-S", ".", "-B", build_dir]
# Additional flags are needed if OpenMP support is requested.
if USE_OPENMP:
cmake_args.append("-DOMP=ON")
# Run CMake to generate the build files.
subprocess.run(cmake_args, check = True)
# Run the build process and compile librssringoccs and libtmpl.
subprocess.run(
["cmake", "--build", build_dir, "--config", "Release", "-j"],
check=True,
)
# Path for Windows users, note the '\' instead of '/'.
if os.name == "nt":
return [
build_dir + "\\Release\\rssringoccs.lib",
build_dir + "\\libtmpl\\Release\\tmpl.lib"
]
# Path for everyone else.
return [
build_dir + "/librssringoccs.a",
build_dir + "/libtmpl/libtmpl.a"
]
# GNU Make is 'gmake' on FreeBSD. Check for this first.
if shutil.which("gmake"):
command = ["gmake", "-j", "BUILD_STATIC=1"]
# GNU Make is simply 'make' on GNU / Linux and macOS.
elif shutil.which("make"):
command = ["make", "-j", "BUILD_STATIC=1"]
else:
raise RuntimeError("Neither CMake nor GNU Make found. Install one.")
# gmake and make have nearly identical build steps. The only difference
# is the name of the command. This is saved in the 'command' variable.
if USE_OPENMP:
command.append("OMP=1")
subprocess.run(command, check = True)
return ["./librssringoccs.a", "./libtmpl/libtmpl.a"]
# Add all of the crssringoccs files (the C-Python API wrapper) to the build.
add_directory("auxiliary")
add_directory("cassini_csv_data")
add_directory("diffraction_correction")
add_directory("merged_csv_data")
add_directory("py_csv_obj")
add_directory("voyager_csv_data")
srclist.append("rss_ringoccs/crssringoccs/crssringoccs.c")
extra_objects = static_library_paths()
compile_args, linker_args = openmp_args()
setup(
name = "rss_ringoccs",
version = "1.3",
description = "C Tools for rss_ringoccs",
author = "Ryan Maguire",
ext_modules = [
Extension(
"crssringoccs",
srclist,
include_dirs = [
numpy.get_include(),
"./",
"../"
],
extra_objects = extra_objects,
extra_compile_args = compile_args,
extra_link_args = linker_args
)
],
packages = [
"rss_ringoccs",
"rss_ringoccs.calibration",
"rss_ringoccs.occgeo",
"rss_ringoccs.rsr_reader",
"rss_ringoccs.scatter",
"rss_ringoccs.tools"
]
)