Skip to content

Commit 298207a

Browse files
authored
Merge pull request #168 from alicevision/dev_docker
Packaging with docker and cmake
2 parents f8d761c + 5bf6250 commit 298207a

File tree

6 files changed

+272
-11
lines changed

6 files changed

+272
-11
lines changed

CMakeLists.txt

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
cmake_minimum_required(VERSION 3.3)
2+
project(meshroom LANGUAGES C CXX)
3+
4+
if(NOT CMAKE_BUILD_TYPE)
5+
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type for Meshroom plugins" FORCE)
6+
endif()
7+
8+
set(ALICEVISION_ROOT "$ENV{ALICEVISION_ROOT}" CACHE STRING "AliceVision root dir")
9+
set(QT_DIR "$ENV{QT_DIR}" CACHE STRING "Qt root directory")
10+
11+
option(MR_BUILD_QTOIIO "Enable building of QtOIIO plugin" ON)
12+
option(MR_BUILD_QMLALEMBIC "Enable building of qmlAlembic plugin" ON)
13+
14+
if(CMAKE_BUILD_TYPE MATCHES Release)
15+
message(STATUS "Force CMAKE_INSTALL_DO_STRIP in Release")
16+
set(CMAKE_INSTALL_DO_STRIP ON)
17+
else()
18+
set(CMAKE_INSTALL_DO_STRIP OFF)
19+
endif()
20+
21+
set(CMAKE_CORE_BUILD_FLAGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_INSTALL_DO_STRIP=${CMAKE_INSTALL_DO_STRIP})
22+
23+
set(OIIO_CMAKE_FLAGS
24+
-DOPENIMAGEIO_LIBRARY_DIR_HINTS=${ALICEVISION_ROOT}/lib64
25+
-DOPENIMAGEIO_INCLUDE_DIR_HINTS=${ALICEVISION_ROOT}/include
26+
-DILMBASE_INCLUDE_PATH=${ALICEVISION_ROOT}/include
27+
-DOPENEXR_INCLUDE_PATH=${ALICEVISION_ROOT}/include
28+
)
29+
set(ALEMBIC_CMAKE_FLAGS
30+
-DAlembic_DIR:PATH=${ALICEVISION_ROOT}/lib64/cmake/Alembic
31+
-DILMBASE_ROOT=${ALICEVISION_ROOT}
32+
)
33+
set(QT_CMAKE_FLAGS -DCMAKE_PREFIX_PATH=${QT_DIR})
34+
35+
36+
include(ExternalProject)
37+
# ==============================================================================
38+
# GNUInstallDirs CMake module
39+
# - Define GNU standard installation directories
40+
# - Provides install directory variables as defined by the GNU Coding Standards.
41+
# ==============================================================================
42+
include(GNUInstallDirs)
43+
44+
# message(STATUS "QT_CMAKE_FLAGS: ${QT_CMAKE_FLAGS}")
45+
46+
if(MR_BUILD_QTOIIO)
47+
set(QTOIIO_TARGET qtoiio)
48+
ExternalProject_Add(${QTOIIO_TARGET}
49+
GIT_REPOSITORY https://github.com/alicevision/QtOIIO
50+
GIT_TAG develop
51+
PREFIX ${BUILD_DIR}
52+
BUILD_IN_SOURCE 0
53+
BUILD_ALWAYS 0
54+
SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/qtoiio
55+
BINARY_DIR ${BUILD_DIR}/qtoiio_build
56+
INSTALL_DIR ${CMAKE_INSTALL_PREFIX}
57+
CONFIGURE_COMMAND ${CMAKE_COMMAND} ${CMAKE_CORE_BUILD_FLAGS} ${OIIO_CMAKE_FLAGS} ${QT_CMAKE_FLAGS} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> <SOURCE_DIR>
58+
)
59+
endif()
60+
61+
62+
if(MR_BUILD_QMLALEMBIC)
63+
set(QMLALEMBIC_TARGET qmlalembic)
64+
ExternalProject_Add(${QMLALEMBIC_TARGET}
65+
GIT_REPOSITORY https://github.com/alicevision/qmlAlembic
66+
GIT_TAG develop
67+
PREFIX ${BUILD_DIR}
68+
BUILD_IN_SOURCE 0
69+
BUILD_ALWAYS 0
70+
SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/qmlalembic
71+
BINARY_DIR ${BUILD_DIR}/qmlalembic_build
72+
INSTALL_DIR ${CMAKE_INSTALL_PREFIX}
73+
CONFIGURE_COMMAND ${CMAKE_COMMAND} ${CMAKE_CORE_BUILD_FLAGS} ${ALEMBIC_CMAKE_FLAGS} ${QT_CMAKE_FLAGS} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> <SOURCE_DIR>
74+
)
75+
endif()
76+

Dockerfile

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
ARG CUDA_TAG=7.0
2+
ARG OS_TAG=7
3+
FROM alicevision:centos${OS_TAG}-cuda${CUDA_TAG}
4+
LABEL maintainer="AliceVision Team [email protected]"
5+
6+
# Execute with nvidia docker (https://github.com/nvidia/nvidia-docker/wiki/Installation-(version-2.0))
7+
# docker run -it --runtime=nvidia meshroom
8+
9+
ENV MESHROOM_DEV=/opt/Meshroom \
10+
MESHROOM_BUILD=/tmp/Meshroom_build \
11+
MESHROOM_BUNDLE=/opt/Meshroom_bundle \
12+
QT_DIR=/opt/qt/5.11.0/gcc_64 \
13+
PATH="${PATH}:${MESHROOM_BUNDLE}"
14+
15+
COPY . "${MESHROOM_DEV}"
16+
17+
# Install libs needed by Qt
18+
RUN yum install -y \
19+
flex \
20+
fontconfig \
21+
freetype \
22+
glib2 \
23+
libICE \
24+
libX11 \
25+
libxcb \
26+
libXext \
27+
libXi \
28+
libXrender \
29+
libSM \
30+
libXt-devel \
31+
libGLU-devel \
32+
mesa-libOSMesa-devel \
33+
mesa-libGL-devel \
34+
mesa-libGLU-devel \
35+
xcb-util-keysyms \
36+
xcb-util-image
37+
38+
# Install Python3
39+
RUN yum install -y centos-release-scl
40+
RUN yum install -y rh-python36
41+
42+
# Install Meshroom requirements and freeze bundle
43+
RUN source scl_source enable rh-python36 && cd "${MESHROOM_DEV}" && pip install -r dev_requirements.txt -r requirements.txt && python setup.py install_exe -d "${MESHROOM_BUNDLE}"
44+
45+
# Install Qt (to build plugins)
46+
WORKDIR /tmp/qt
47+
RUN curl -LO http://download.qt.io/official_releases/online_installers/qt-unified-linux-x64-online.run
48+
RUN chmod u+x qt-unified-linux-x64-online.run
49+
RUN ./qt-unified-linux-x64-online.run --verbose --platform minimal --script "${MESHROOM_DEV}/docker/qt-installer-noninteractive.qs"
50+
51+
WORKDIR ${MESHROOM_BUILD}
52+
# Temporary workaround for qmlAlembic build
53+
RUN rm -rf "${AV_INSTALL}/lib" && ln -s "${AV_INSTALL}/lib64" "${AV_INSTALL}/lib"
54+
55+
# Build Meshroom plugins
56+
RUN cmake "${MESHROOM_DEV}" -DALICEVISION_ROOT="${AV_INSTALL}" -DQT_DIR="${QT_DIR}" -DCMAKE_INSTALL_PREFIX="${MESHROOM_BUNDLE}/qtPlugins"
57+
RUN make -j8
58+
59+
RUN mv "${AV_BUNDLE}" "${MESHROOM_BUNDLE}/aliceVision"
60+
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Emacs mode hint: -*- mode: JavaScript -*-
2+
3+
function Controller() {
4+
installer.autoRejectMessageBoxes();
5+
installer.installationFinished.connect(function() {
6+
gui.clickButton(buttons.NextButton);
7+
})
8+
9+
// Copied from https://bugreports.qt.io/browse/QTIFW-1072?jql=project%20%3D%20QTIFW
10+
// there are some changes between Qt Online installer 3.0.1 and 3.0.2. Welcome page does some network
11+
// queries that is why the next button is called too early.
12+
var page = gui.pageWidgetByObjectName("WelcomePage")
13+
page.completeChanged.connect(welcomepageFinished)
14+
}
15+
16+
Controller.prototype.WelcomePageCallback = function() {
17+
gui.clickButton(buttons.NextButton);
18+
}
19+
20+
welcomepageFinished = function()
21+
{
22+
//completeChange() -function is called also when other pages visible
23+
//Make sure that next button is clicked only when in welcome page
24+
if(gui.currentPageWidget().objectName == "WelcomePage") {
25+
gui.clickButton( buttons.NextButton);
26+
}
27+
}
28+
29+
Controller.prototype.CredentialsPageCallback = function() {
30+
gui.clickButton(buttons.NextButton);
31+
}
32+
33+
Controller.prototype.IntroductionPageCallback = function() {
34+
gui.clickButton(buttons.NextButton);
35+
}
36+
37+
Controller.prototype.TargetDirectoryPageCallback = function()
38+
{
39+
gui.currentPageWidget().TargetDirectoryLineEdit.setText("/opt/qt");
40+
gui.clickButton(buttons.NextButton);
41+
}
42+
43+
Controller.prototype.ComponentSelectionPageCallback = function() {
44+
var widget = gui.currentPageWidget();
45+
46+
widget.deselectAll();
47+
48+
// widget.selectComponent("qt");
49+
// widget.selectComponent("qt.qt5.5110");
50+
widget.selectComponent("qt.qt5.5110.gcc_64");
51+
// widget.selectComponent("qt.qt5.5110.qtscript");
52+
// widget.selectComponent("qt.qt5.5110.qtscript.gcc_64");
53+
// widget.selectComponent("qt.qt5.5110.qtwebengine");
54+
// widget.selectComponent("qt.qt5.5110.qtwebengine.gcc_64");
55+
// widget.selectComponent("qt.qt5.5110.qtwebglplugin");
56+
// widget.selectComponent("qt.qt5.5110.qtwebglplugin.gcc_64");
57+
// widget.selectComponent("qt.tools");
58+
59+
gui.clickButton(buttons.NextButton);
60+
}
61+
62+
Controller.prototype.LicenseAgreementPageCallback = function() {
63+
gui.currentPageWidget().AcceptLicenseRadioButton.setChecked(true);
64+
gui.clickButton(buttons.NextButton);
65+
}
66+
67+
Controller.prototype.StartMenuDirectoryPageCallback = function() {
68+
gui.clickButton(buttons.NextButton);
69+
}
70+
71+
Controller.prototype.ReadyForInstallationPageCallback = function()
72+
{
73+
gui.clickButton(buttons.NextButton);
74+
}
75+
76+
Controller.prototype.FinishedPageCallback = function() {
77+
var checkBoxForm = gui.currentPageWidget().LaunchQtCreatorCheckBoxForm
78+
if (checkBoxForm && checkBoxForm.launchQtCreatorCheckBox) {
79+
checkBoxForm.launchQtCreatorCheckBox.checked = false;
80+
}
81+
gui.clickButton(buttons.FinishButton);
82+
}
83+

meshroom/__init__.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@ def setupEnvironment():
2727
2828
- Meshroom/
2929
- aliceVision/
30-
- bin/ # runtime bundled binaries (exe + libs)
30+
- bin/ # runtime bundled binaries (windows: exe + libs, unix: executables)
31+
- lib/ # runtime bundled libraries (unix: libs)
3132
- share/ # resource files
32-
- COPYING.md # AliceVision COPYING file
33-
- cameraSensors.db # sensor database
34-
- vlfeat_K80L3.tree # voctree file
33+
- aliceVision/
34+
- COPYING.md # AliceVision COPYING file
35+
- cameraSensors.db # sensor database
36+
- vlfeat_K80L3.tree # voctree file
3537
- lib/ # Python lib folder
3638
- qtPlugins/
3739
Meshroom # main executable
@@ -58,27 +60,24 @@ def addToEnvPath(var, val, index=-1):
5860
paths[index:index] = val
5961
os.environ[var] = os.pathsep.join(paths)
6062

61-
# detect if this is a frozen environment based on executable name
62-
isStandalone = "python" not in os.path.basename(sys.executable).lower()
63+
# sys.frozen is initialized by cx_Freeze
64+
isFrozen = getattr(sys, "frozen", False)
6365
# setup root directory (override possible by setting "MESHROOM_INSTALL_DIR" environment variable)
64-
rootDir = os.path.dirname(sys.executable) if isStandalone else os.environ.get("MESHROOM_INSTALL_DIR", None)
66+
rootDir = os.path.dirname(sys.executable) if isFrozen else os.environ.get("MESHROOM_INSTALL_DIR", None)
6567

6668
if rootDir:
6769
os.environ["MESHROOM_INSTALL_DIR"] = rootDir
6870

6971
aliceVisionDir = os.path.join(rootDir, "aliceVision")
7072
# default directories
7173
aliceVisionBinDir = os.path.join(aliceVisionDir, "bin")
72-
aliceVisionShareDir = os.path.join(aliceVisionDir, "share")
74+
aliceVisionShareDir = os.path.join(aliceVisionDir, "share", "aliceVision")
7375
qtPluginsDir = os.path.join(rootDir, "qtPlugins")
7476
sensorDBPath = os.path.join(aliceVisionShareDir, "cameraSensors.db")
7577
voctreePath = os.path.join(aliceVisionShareDir, "vlfeat_K80L3.tree")
76-
# Linux: "lib" contains shared libraries that needs to be in LD_LIBRARY_PATH
77-
libPath = os.path.join(rootDir, "lib")
7878

7979
env = {
8080
'PATH': aliceVisionBinDir,
81-
'LD_LIBRARY_PATH': [aliceVisionBinDir, libPath],
8281
'QT_PLUGIN_PATH': [qtPluginsDir],
8382
'QML2_IMPORT_PATH': [os.path.join(qtPluginsDir, "qml")]
8483
}

setup.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ def __init__(self, script, initScript=None, base=None, targetName=None, icons=No
3131
targetName += PlatformExecutable.exeExtensions[platform.system()]
3232
# get icon for platform if defined
3333
icon = icons.get(platform.system(), None) if icons else None
34+
if platform.system() in (self.Linux, self.Darwin):
35+
currentDir = os.path.dirname(os.path.abspath(__file__))
36+
initScript = os.path.join(currentDir, "setupInitScriptUnix.py")
3437
super(PlatformExecutable, self).__init__(script, initScript, base, targetName, icon, shortcutName,
3538
shortcutDir, copyright, trademarks)
3639

setupInitScriptUnix.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#------------------------------------------------------------------------------
2+
# ConsoleSetLibPath.py
3+
# Initialization script for cx_Freeze which manipulates the path so that the
4+
# directory in which the executable is found is searched for extensions but
5+
# no other directory is searched. The environment variable LD_LIBRARY_PATH is
6+
# manipulated first, however, to ensure that shared libraries found in the
7+
# target directory are found. This requires a restart of the executable because
8+
# the environment variable LD_LIBRARY_PATH is only checked at startup.
9+
#------------------------------------------------------------------------------
10+
11+
import os
12+
import sys
13+
import zipimport
14+
15+
FILE_NAME = sys.executable
16+
DIR_NAME = os.path.dirname(sys.executable)
17+
18+
paths = os.environ.get("LD_LIBRARY_PATH", "").split(os.pathsep)
19+
20+
if DIR_NAME not in paths:
21+
paths.insert(0, DIR_NAME)
22+
paths.insert(0, os.path.join(DIR_NAME, "lib"))
23+
paths.insert(0, os.path.join(DIR_NAME, "aliceVision", "lib"))
24+
paths.insert(0, os.path.join(DIR_NAME, "aliceVision", "lib64"))
25+
26+
os.environ["LD_LIBRARY_PATH"] = os.pathsep.join(paths)
27+
os.execv(sys.executable, sys.argv)
28+
29+
sys.frozen = True
30+
sys.path = sys.path[:4]
31+
32+
33+
def run():
34+
m = __import__("__main__")
35+
importer = zipimport.zipimporter(os.path.dirname(os.__file__))
36+
name, ext = os.path.splitext(os.path.basename(os.path.normcase(FILE_NAME)))
37+
moduleName = "%s__main__" % name
38+
code = importer.get_code(moduleName)
39+
exec(code, m.__dict__)
40+

0 commit comments

Comments
 (0)