Skip to content

Commit f191388

Browse files
authored
Merge pull request #1685 from talregev/TalR/test_python_windows
2 parents 2bc7be2 + b104fd6 commit f191388

File tree

10 files changed

+177
-14
lines changed

10 files changed

+177
-14
lines changed

.github/scripts/python.sh

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,21 @@ function build()
6565
# Set to 2 cores so that Actions does not error out during resource provisioning.
6666
cmake --build build -j2
6767

68-
$PYTHON -m pip install --user build/python
68+
cmake --build build --target python-install
6969
}
7070

7171
function test()
7272
{
7373
cd $GITHUB_WORKSPACE/python/gtsam/tests
7474
$PYTHON -m unittest discover -v
7575
cd $GITHUB_WORKSPACE
76+
77+
cd $GITHUB_WORKSPACE/python/gtsam_unstable/tests
78+
$PYTHON -m unittest discover -v
79+
cd $GITHUB_WORKSPACE
80+
81+
# cmake --build build --target python-test
82+
# cmake --build build --target python-test-unstable
7683
}
7784

7885
# select between build or test

.github/workflows/build-python.yml

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ jobs:
1818
CTEST_PARALLEL_LEVEL: 2
1919
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
2020
PYTHON_VERSION: ${{ matrix.python_version }}
21+
BOOST_VERSION: 1.72.0
22+
BOOST_EXE: boost_1_72_0-msvc-14.2
2123

2224
strategy:
2325
fail-fast: true
@@ -30,6 +32,7 @@ jobs:
3032
ubuntu-20.04-gcc-9-tbb,
3133
ubuntu-20.04-clang-9,
3234
macOS-11-xcode-13.4.1,
35+
windows-2019-msbuild,
3336
]
3437

3538
build_type: [Release]
@@ -56,6 +59,10 @@ jobs:
5659
compiler: xcode
5760
version: "13.4.1"
5861

62+
- name: windows-2019-msbuild
63+
os: windows-2019
64+
platform: 64
65+
5966
steps:
6067
- name: Checkout
6168
uses: actions/checkout@v3
@@ -97,29 +104,68 @@ jobs:
97104
echo "CC=clang" >> $GITHUB_ENV
98105
echo "CXX=clang++" >> $GITHUB_ENV
99106
107+
- name: Setup msbuild (Windows)
108+
if: runner.os == 'Windows'
109+
uses: ilammy/msvc-dev-cmd@v1
110+
with:
111+
arch: x${{matrix.platform}}
112+
113+
- name: Setup python (Windows)
114+
uses: actions/setup-python@v4
115+
if: runner.os == 'Windows'
116+
with:
117+
python-version: ${{ matrix.python_version }}
118+
119+
- name: Install ninja (Windows)
120+
if: runner.os == 'Windows'
121+
shell: bash
122+
run: |
123+
choco install ninja
124+
ninja --version
125+
where ninja
126+
127+
- name: Install Boost (Windows)
128+
if: runner.os == 'Windows'
129+
shell: powershell
130+
run: |
131+
# Snippet from: https://github.com/actions/virtual-environments/issues/2667
132+
$BOOST_PATH = "C:\hostedtoolcache\windows\Boost\$env:BOOST_VERSION\x86_64"
133+
134+
# Use the prebuilt binary for Windows
135+
$Url = "https://sourceforge.net/projects/boost/files/boost-binaries/$env:BOOST_VERSION/$env:BOOST_EXE-${{matrix.platform}}.exe"
136+
(New-Object System.Net.WebClient).DownloadFile($Url, "$env:TEMP\boost.exe")
137+
Start-Process -Wait -FilePath "$env:TEMP\boost.exe" "/SILENT","/SP-","/SUPPRESSMSGBOXES","/DIR=$BOOST_PATH"
138+
139+
# Set the BOOST_ROOT variable
140+
echo "BOOST_ROOT=$BOOST_PATH" >> $env:GITHUB_ENV
141+
100142
- name: Set GTSAM_WITH_TBB Flag
101143
if: matrix.flag == 'tbb'
102144
run: |
103145
echo "GTSAM_WITH_TBB=ON" >> $GITHUB_ENV
104146
echo "GTSAM Uses TBB"
105147
106-
- name: Set Swap Space
148+
- name: Set Swap Space (Linux)
107149
if: runner.os == 'Linux'
108150
uses: pierotofy/set-swap-space@master
109151
with:
110152
swap-size-gb: 6
111153

112-
- name: Install System Dependencies
154+
- name: Install System Dependencies (Linux, macOS)
155+
if: runner.os != 'Windows'
113156
run: |
114157
bash .github/scripts/python.sh -d
115158
116159
- name: Install Python Dependencies
160+
shell: bash
117161
run: python$PYTHON_VERSION -m pip install -r python/dev_requirements.txt
118162

119163
- name: Build
164+
shell: bash
120165
run: |
121166
bash .github/scripts/python.sh -b
122167
123168
- name: Test
169+
shell: bash
124170
run: |
125171
bash .github/scripts/python.sh -t

gtsam/base/utilities.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@
44
#include <iostream>
55
#include <sstream>
66

7+
#include <gtsam/dllexport.h>
8+
79
namespace gtsam {
810
/**
911
* For Python __str__().
1012
* Redirect std cout to a string stream so we can return a string representation
1113
* of an object when it prints to cout.
1214
* https://stackoverflow.com/questions/5419356/redirect-stdout-stderr-to-a-string
1315
*/
14-
struct RedirectCout {
16+
struct GTSAM_EXPORT RedirectCout {
1517
/// constructor -- redirect stdout buffer to a stringstream buffer
1618
RedirectCout() : ssBuffer_(), coutBuffer_(std::cout.rdbuf(ssBuffer_.rdbuf())) {}
1719

gtsam/discrete/DiscreteValues.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,12 @@ inline std::vector<DiscreteValues> cartesianProduct(const DiscreteKeys& keys) {
126126
}
127127

128128
/// Free version of markdown.
129-
std::string markdown(const DiscreteValues& values,
129+
std::string GTSAM_EXPORT markdown(const DiscreteValues& values,
130130
const KeyFormatter& keyFormatter = DefaultKeyFormatter,
131131
const DiscreteValues::Names& names = {});
132132

133133
/// Free version of html.
134-
std::string html(const DiscreteValues& values,
134+
std::string GTSAM_EXPORT html(const DiscreteValues& values,
135135
const KeyFormatter& keyFormatter = DefaultKeyFormatter,
136136
const DiscreteValues::Names& names = {});
137137

gtsam/geometry/Rot3.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ class GTSAM_EXPORT Rot3 : public LieGroup<Rot3, 3> {
396396
Matrix3 AdjointMap() const { return matrix(); }
397397

398398
// Chart at origin, depends on compile-time flag ROT3_DEFAULT_COORDINATES_MODE
399-
struct ChartAtOrigin {
399+
struct GTSAM_EXPORT ChartAtOrigin {
400400
static Rot3 Retract(const Vector3& v, ChartJacobian H = {});
401401
static Vector3 Local(const Rot3& r, ChartJacobian H = {});
402402
};

gtsam/nonlinear/CustomFactor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ using CustomErrorFunction = std::function<Vector(const CustomFactor &, const Val
4242
*
4343
* This factor is mainly for creating a custom factor in Python.
4444
*/
45-
class CustomFactor: public NoiseModelFactor {
45+
class GTSAM_EXPORT CustomFactor: public NoiseModelFactor {
4646
protected:
4747
CustomErrorFunction error_function_;
4848

gtsam/nonlinear/Values-inl.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,61 @@ namespace gtsam {
197197
}
198198
};
199199

200+
// Added this section for compile gtsam python on windows.
201+
// msvc don't deduct the template arguments correctly, due possible bug in msvc.
202+
#ifdef _WIN32
203+
// Handle dynamic matrices
204+
template <int M, int N>
205+
struct handle_matrix<Eigen::Matrix<double, M, N, 0, M, N>, true> {
206+
inline Eigen::Matrix<double, M, N> operator()(Key j, const Value* const pointer) {
207+
auto ptr = dynamic_cast<const GenericValue<Eigen::Matrix<double, M, N>>*>(pointer);
208+
if (ptr) {
209+
// value returns a const Matrix&, and the return makes a copy !!!!!
210+
return ptr->value();
211+
} else {
212+
// If a fixed matrix was stored, we end up here as well.
213+
throw ValuesIncorrectType(j, typeid(*pointer), typeid(Eigen::Matrix<double, M, N>));
214+
}
215+
}
216+
};
217+
218+
// Handle fixed matrices
219+
template <int M, int N>
220+
struct handle_matrix<Eigen::Matrix<double, M, N, 0, M, N>, false> {
221+
inline Eigen::Matrix<double, M, N> operator()(Key j, const Value* const pointer) {
222+
auto ptr = dynamic_cast<const GenericValue<Eigen::Matrix<double, M, N>>*>(pointer);
223+
if (ptr) {
224+
// value returns a const MatrixMN&, and the return makes a copy !!!!!
225+
return ptr->value();
226+
} else {
227+
Matrix A;
228+
// Check if a dynamic matrix was stored
229+
auto ptr = dynamic_cast<const GenericValue<Eigen::MatrixXd>*>(pointer);
230+
if (ptr) {
231+
A = ptr->value();
232+
} else {
233+
// Or a dynamic vector
234+
A = handle_matrix<Eigen::VectorXd, true>()(j, pointer); // will throw if not....
235+
}
236+
// Yes: check size, and throw if not a match
237+
if (A.rows() != M || A.cols() != N)
238+
throw NoMatchFoundForFixed(M, N, A.rows(), A.cols());
239+
else
240+
return A; // copy but not malloc
241+
}
242+
}
243+
};
244+
245+
// Handle matrices
246+
template <int M, int N>
247+
struct handle<Eigen::Matrix<double, M, N, 0, M, N>> {
248+
Eigen::Matrix<double, M, N> operator()(Key j, const Value* const pointer) {
249+
return handle_matrix<Eigen::Matrix<double, M, N, 0, M, N>,
250+
(M == Eigen::Dynamic || N == Eigen::Dynamic)>()(j, pointer);
251+
}
252+
};
253+
#endif // #ifdef _WIN32
254+
200255
} // internal
201256

202257
/* ************************************************************************* */

gtsam/sfm/DsfTrackGenerator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ using MatchIndicesMap = std::map<IndexPair, CorrespondenceIndices>;
6969
* correspondence indices, from each image.
7070
* @param Length-N list of keypoints, for N images/cameras.
7171
*/
72-
std::vector<SfmTrack2d> tracksFromPairwiseMatches(
72+
std::vector<SfmTrack2d> GTSAM_EXPORT tracksFromPairwiseMatches(
7373
const MatchIndicesMap& matches, const KeypointsVector& keypoints,
7474
bool verbose = false);
7575

python/CMakeLists.txt

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,14 @@ set(interface_headers
9494
set(GTSAM_PYTHON_TARGET gtsam_py)
9595
set(GTSAM_PYTHON_UNSTABLE_TARGET gtsam_unstable_py)
9696

97+
set(GTSAM_OUTPUT_NAME "gtsam")
98+
set(GTSAM_UNSTABLE_OUTPUT_NAME "gtsam_unstable")
99+
100+
if(MSVC)
101+
set(GTSAM_OUTPUT_NAME "gtsam_py")
102+
set(GTSAM_UNSTABLE_OUTPUT_NAME "gtsam_unstable_py")
103+
endif()
104+
97105
pybind_wrap(${GTSAM_PYTHON_TARGET} # target
98106
"${interface_headers}" # interface_headers
99107
"gtsam.cpp" # generated_cpp
@@ -109,12 +117,30 @@ pybind_wrap(${GTSAM_PYTHON_TARGET} # target
109117
set_target_properties(${GTSAM_PYTHON_TARGET} PROPERTIES
110118
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib"
111119
INSTALL_RPATH_USE_LINK_PATH TRUE
112-
OUTPUT_NAME "gtsam"
120+
OUTPUT_NAME "${GTSAM_OUTPUT_NAME}"
113121
LIBRARY_OUTPUT_DIRECTORY "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam"
114122
DEBUG_POSTFIX "" # Otherwise you will have a wrong name
115123
RELWITHDEBINFO_POSTFIX "" # Otherwise you will have a wrong name
116124
)
117125

126+
if(WIN32)
127+
set_target_properties(${GTSAM_PYTHON_TARGET} PROPERTIES
128+
SUFFIX ".pyd"
129+
)
130+
ADD_CUSTOM_COMMAND(TARGET ${GTSAM_PYTHON_TARGET} POST_BUILD
131+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
132+
"${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam/${GTSAM_OUTPUT_NAME}.pyd"
133+
"${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam/gtsam.pyd"
134+
)
135+
ADD_CUSTOM_COMMAND(TARGET ${GTSAM_PYTHON_TARGET} POST_BUILD
136+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
137+
"$<TARGET_FILE:gtsam>;$<TARGET_RUNTIME_DLLS:gtsam>"
138+
"${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam/"
139+
COMMAND_EXPAND_LISTS
140+
VERBATIM
141+
)
142+
endif()
143+
118144
# Set the path for the GTSAM python module
119145
set(GTSAM_MODULE_PATH ${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam)
120146

@@ -188,7 +214,7 @@ if(GTSAM_UNSTABLE_BUILD_PYTHON)
188214
set_target_properties(${GTSAM_PYTHON_UNSTABLE_TARGET} PROPERTIES
189215
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib"
190216
INSTALL_RPATH_USE_LINK_PATH TRUE
191-
OUTPUT_NAME "gtsam_unstable"
217+
OUTPUT_NAME "${GTSAM_UNSTABLE_OUTPUT_NAME}"
192218
LIBRARY_OUTPUT_DIRECTORY "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam_unstable"
193219
DEBUG_POSTFIX "" # Otherwise you will have a wrong name
194220
RELWITHDEBINFO_POSTFIX "" # Otherwise you will have a wrong name
@@ -208,13 +234,39 @@ if(GTSAM_UNSTABLE_BUILD_PYTHON)
208234

209235
# Add gtsam_unstable to the install target
210236
list(APPEND GTSAM_PYTHON_DEPENDENCIES ${GTSAM_PYTHON_UNSTABLE_TARGET})
211-
237+
if(WIN32)
238+
set_target_properties(${GTSAM_PYTHON_UNSTABLE_TARGET} PROPERTIES
239+
SUFFIX ".pyd"
240+
)
241+
ADD_CUSTOM_COMMAND(TARGET ${GTSAM_PYTHON_UNSTABLE_TARGET} POST_BUILD
242+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
243+
"${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam_unstable/${GTSAM_UNSTABLE_OUTPUT_NAME}.pyd"
244+
"${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam_unstable/gtsam_unstable.pyd"
245+
)
246+
ADD_CUSTOM_COMMAND(TARGET ${GTSAM_PYTHON_UNSTABLE_TARGET} POST_BUILD
247+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
248+
"$<TARGET_FILE:gtsam_unstable>;$<TARGET_RUNTIME_DLLS:gtsam_unstable>"
249+
"${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam_unstable/"
250+
COMMAND_EXPAND_LISTS
251+
VERBATIM
252+
)
253+
endif()
254+
# Custom make command to run all GTSAM_UNSTABLE Python tests
255+
add_custom_target(
256+
python-test-unstable
257+
COMMAND
258+
${CMAKE_COMMAND} -E env # add package to python path so no need to install
259+
"PYTHONPATH=${GTSAM_PYTHON_BUILD_DIRECTORY}/$ENV{PYTHONPATH}"
260+
${PYTHON_EXECUTABLE} -m unittest discover -v -s .
261+
DEPENDS ${GTSAM_PYTHON_DEPENDENCIES} ${GTSAM_PYTHON_TEST_FILES}
262+
WORKING_DIRECTORY "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam_unstable/tests"
263+
)
212264
endif()
213265

214266
# Add custom target so we can install with `make python-install`
215267
set(GTSAM_PYTHON_INSTALL_TARGET python-install)
216268
add_custom_target(${GTSAM_PYTHON_INSTALL_TARGET}
217-
COMMAND ${PYTHON_EXECUTABLE} -m pip install .
269+
COMMAND ${PYTHON_EXECUTABLE} -m pip install --user .
218270
DEPENDS ${GTSAM_PYTHON_DEPENDENCIES}
219271
WORKING_DIRECTORY ${GTSAM_PYTHON_BUILD_DIRECTORY})
220272

python/setup.py.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ print("PACKAGES: ", packages)
1111
package_data = {
1212
'': [
1313
"./*.so",
14-
"./*.dll"
14+
"./*.dll",
15+
"./*.pyd",
1516
]
1617
}
1718

0 commit comments

Comments
 (0)