diff --git a/CMakeLists.txt b/CMakeLists.txt index fcf0f24d2..3b1ec784b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ project( calamares CXX ) cmake_minimum_required( VERSION 3.2 ) -set( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules" ) +set( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules" ) set( CMAKE_CXX_STANDARD 14 ) set( CMAKE_CXX_STANDARD_REQUIRED ON ) @@ -180,12 +180,7 @@ configure_file( ) # Early configure these files as we need them later on -configure_file( CalamaresUse.cmake.in "${PROJECT_BINARY_DIR}/CalamaresUse.cmake" @ONLY ) -file( COPY CalamaresAddLibrary.cmake DESTINATION "${PROJECT_BINARY_DIR}" ) -file( COPY CalamaresAddModuleSubdirectory.cmake DESTINATION "${PROJECT_BINARY_DIR}" ) -file( COPY CalamaresAddPlugin.cmake DESTINATION "${PROJECT_BINARY_DIR}" ) -file( COPY CalamaresAddBrandingSubdirectory.cmake DESTINATION "${PROJECT_BINARY_DIR}" ) - +set( CALAMARES_CMAKE_DIR "${CMAKE_SOURCE_DIR}/CMakeModules" ) set( CALAMARES_LIBRARIES calamares ) set( THIRDPARTY_DIR "${CMAKE_SOURCE_DIR}/thirdparty" ) @@ -231,11 +226,10 @@ install( FILES "${PROJECT_BINARY_DIR}/CalamaresConfig.cmake" "${PROJECT_BINARY_DIR}/CalamaresConfigVersion.cmake" - "${PROJECT_BINARY_DIR}/CalamaresUse.cmake" - "${PROJECT_BINARY_DIR}/CalamaresAddPlugin.cmake" - "${PROJECT_BINARY_DIR}/CalamaresAddModuleSubdirectory.cmake" - "${PROJECT_BINARY_DIR}/CalamaresAddLibrary.cmake" - "${PROJECT_BINARY_DIR}/CalamaresAddBrandingSubdirectory.cmake" + "CmakeModules/CalamaresAddPlugin.cmake" + "CmakeModules/CalamaresAddModuleSubdirectory.cmake" + "CmakeModules/CalamaresAddLibrary.cmake" + "CmakeModules/CalamaresAddBrandingSubdirectory.cmake" DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" ) diff --git a/CMakeModules/CMakeColors.cmake b/CMakeModules/CMakeColors.cmake index 4b96ac8a8..7a9a13e1d 100644 --- a/CMakeModules/CMakeColors.cmake +++ b/CMakeModules/CMakeColors.cmake @@ -1,8 +1,13 @@ if(NOT WIN32) - # [ -t 2 ] tests whether stderr is interactive. - # The negation '!' is because for POSIX shells, 0 is true and 1 is false. - execute_process(COMMAND test ! -t 2 RESULT_VARIABLE IS_STDERR_INTERACTIVE) - if(IS_STDERR_INTERACTIVE) + set(_use_color ON) + if("0" STREQUAL "$ENV{CLICOLOR}") + set(_use_color OFF) + endif() + if("0" STREQUAL "$ENV{CLICOLOR_FORCE}") + set(_use_color OFF) + endif() + + if(_use_color) string(ASCII 27 Esc) set(ColorReset "${Esc}[m") set(ColorBold "${Esc}[1m") @@ -20,5 +25,5 @@ if(NOT WIN32) set(BoldMagenta "${Esc}[1;35m") set(BoldCyan "${Esc}[1;36m") set(BoldWhite "${Esc}[1;37m") - endif(IS_STDERR_INTERACTIVE) + endif() endif() diff --git a/CalamaresAddBrandingSubdirectory.cmake b/CMakeModules/CalamaresAddBrandingSubdirectory.cmake similarity index 100% rename from CalamaresAddBrandingSubdirectory.cmake rename to CMakeModules/CalamaresAddBrandingSubdirectory.cmake diff --git a/CalamaresAddLibrary.cmake b/CMakeModules/CalamaresAddLibrary.cmake similarity index 100% rename from CalamaresAddLibrary.cmake rename to CMakeModules/CalamaresAddLibrary.cmake diff --git a/CalamaresAddModuleSubdirectory.cmake b/CMakeModules/CalamaresAddModuleSubdirectory.cmake similarity index 100% rename from CalamaresAddModuleSubdirectory.cmake rename to CMakeModules/CalamaresAddModuleSubdirectory.cmake diff --git a/CalamaresAddPlugin.cmake b/CMakeModules/CalamaresAddPlugin.cmake similarity index 77% rename from CalamaresAddPlugin.cmake rename to CMakeModules/CalamaresAddPlugin.cmake index b2847f7a9..560638de8 100644 --- a/CalamaresAddPlugin.cmake +++ b/CMakeModules/CalamaresAddPlugin.cmake @@ -1,5 +1,28 @@ +# Convenience function for creating a C++ (qtplugin) module for Calamares. +# This function provides cmake-time feedback about the plugin, adds +# targets for compilation and boilerplate information, and creates +# a module.desc with standard values if none is provided (which only +# happens for very unusual plugins). +# +# Usage: +# +# calamaers_add_plugin( +# module-name +# TYPE +# EXPORT_MACRO macro-name +# SOURCES source-file... +# UI ui-file... +# LINK_LIBRARIES lib... +# LINK_PRIVATE_LIBRARIES lib... +# COMPILE_DEFINITIONS def... +# RESOURCES resource-file +# [NO_INSTALL] +# [SHARED_LIB] +# ) + include( CMakeParseArguments ) -include( ${CALAMARES_CMAKE_DIR}/CalamaresAddLibrary.cmake ) +include( CalamaresAddLibrary ) +include( CMakeColors ) function( calamares_add_plugin ) # parse arguments ( name needs to be saved before passing ARGN into the macro ) @@ -17,7 +40,6 @@ function( calamares_add_plugin ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" ) set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" ) - include( CMakeColors ) message( "-- ${BoldYellow}Found ${CALAMARES_APPLICATION_NAME} module: ${BoldRed}${PLUGIN_NAME}${ColorReset}" ) if( NOT CMAKE_BUILD_TYPE STREQUAL "Release" ) message( " ${Green}TYPE:${ColorReset} ${PLUGIN_TYPE}" ) @@ -83,7 +105,15 @@ function( calamares_add_plugin ) calamares_add_library( ${calamares_add_library_args} ) - configure_file( ${PLUGIN_DESC_FILE} ${PLUGIN_DESC_FILE} COPYONLY ) + if ( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PLUGIN_DESC_FILE} ) + configure_file( ${PLUGIN_DESC_FILE} ${PLUGIN_DESC_FILE} COPYONLY ) + else() + set( _file ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_DESC_FILE} ) + set( _type ${PLUGIN_TYPE} ) + file( WRITE ${_file} "# AUTO-GENERATED metadata file\n# Syntax is YAML 1.2\n---\n" ) + file( APPEND ${_file} "type: \"${_type}\"\nname: \"${PLUGIN_NAME}\"\ninterface: \"qtplugin\"\nload: \"lib${target}.so\"\n" ) + endif() + install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_DESC_FILE} DESTINATION ${PLUGIN_DESTINATION} ) diff --git a/CalamaresUse.cmake.in b/CalamaresUse.cmake.in deleted file mode 100644 index 4e8d67ba5..000000000 --- a/CalamaresUse.cmake.in +++ /dev/null @@ -1,12 +0,0 @@ -#FIXME: this duplicates top level cmakelists: how can we reduce code duplication? - -find_package( Qt5 5.3.0 CONFIG REQUIRED Core Gui Widgets LinguistTools ) - -if(NOT CALAMARES_CMAKE_DIR) - set(CALAMARES_CMAKE_DIR ${CMAKE_CURRENT_LIST_DIR}) -endif() - -include( "${CALAMARES_CMAKE_DIR}/CalamaresAddLibrary.cmake" ) -include( "${CALAMARES_CMAKE_DIR}/CalamaresAddModuleSubdirectory.cmake" ) -include( "${CALAMARES_CMAKE_DIR}/CalamaresAddPlugin.cmake" ) -include( "${CALAMARES_CMAKE_DIR}/CalamaresAddBrandingSubdirectory.cmake" ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ff08b6ae5..4ef6afcbb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,7 @@ -include( ${PROJECT_BINARY_DIR}/CalamaresUse.cmake ) +include( CalamaresAddPlugin ) +include( CalamaresAddModuleSubdirectory ) +include( CalamaresAddLibrary ) +include( CalamaresAddBrandingSubdirectory ) include_directories( ${CMAKE_CURRENT_BINARY_DIR}/libcalamares ) include_directories( ${CMAKE_CURRENT_LIST_DIR}/libcalamares ) diff --git a/src/libcalamaresui/modulesystem/Module.cpp b/src/libcalamaresui/modulesystem/Module.cpp index 09386d58c..96ec0cceb 100644 --- a/src/libcalamaresui/modulesystem/Module.cpp +++ b/src/libcalamaresui/modulesystem/Module.cpp @@ -76,7 +76,7 @@ Module::fromDescriptor( const QVariantMap& moduleDescriptor, << instanceId; return nullptr; } - if ( typeString == "view" ) + if ( ( typeString == "view" ) || ( typeString == "viewmodule" ) ) { if ( intfString == "qtplugin" ) { @@ -90,6 +90,8 @@ Module::fromDescriptor( const QVariantMap& moduleDescriptor, cLog() << "PythonQt modules are not supported in this version of Calamares."; #endif } + else + cLog() << "Bad interface" << intfString << "for module type" << typeString; } else if ( typeString == "job" ) { @@ -109,7 +111,12 @@ Module::fromDescriptor( const QVariantMap& moduleDescriptor, cLog() << "Python modules are not supported in this version of Calamares."; #endif } + else + cLog() << "Bad interface" << intfString << "for module type" << typeString; } + else + cLog() << "Bad module type" << typeString; + if ( !m ) { cLog() << "Bad module type (" << typeString diff --git a/src/modules/README.md b/src/modules/README.md index 386d15a48..80a8ffbd9 100644 --- a/src/modules/README.md +++ b/src/modules/README.md @@ -1,60 +1,119 @@ -Calamares modules -=== +# Calamares modules + +Calamares modules are plugins that provide features like installer pages, +batch jobs, etc. An installer page (visible to the user) is called a "view", +while other modules are "jobs". -Calamares modules are plugins that provide features like installer pages, batch jobs, etc. Each Calamares module lives in its own directory. All modules are installed in `$DESTDIR/lib/calamares/modules`. -### Module directory and descriptor -A Calamares module must have a *module descriptor file*, named `module.desc`, this file must be placed in the module's -directory. -The module descriptor file is a YAML 1.2 document which defines the module's name, type, interface and possibly other -properties. The name of the module as defined in `module.desc` must be the same as the name of the module's directory. +# Module types There are two types of Calamares module: -* viewmodule, -* jobmodule. +* viewmodule, for user-visible modules. These may be in C++, or PythonQt. +* jobmodule, for not-user-visible modules. These may be done in C++, + Python, or as external processes. + +# Module interfaces -There are three interfaces for Calamares modules: +There are three (four) interfaces for Calamares modules: * qtplugin, -* python, -* process. +* python (jobmodules only), +* pythonqt (optional), +* process (jobmodules only). + +# Module directory + +Each Calamares module lives in its own directory. The contents +of the directory depend on the interface and type of the module. + +## Module descriptor -### Module-specific configuration -A Calamares module *may* read a module configuration file, named `.conf`. If such a file is present in the +A Calamares module must have a *module descriptor file*, named +`module.desc`. For C++ (qtplugin) modules using CMake as a build- +system and using the calamares_add_plugin() function -- this is the +recommended way to create such modules -- the module descriptor +file is optional, since it can be generated by the build system. +For other module interfaces, the module descriptor file is required. + +The module descriptor file must be placed in the module's directory. +The module descriptor file is a YAML 1.2 document which defines the +module's name, type, interface and possibly other properties. The name +of the module as defined in `module.desc` must be the same as the name +of the module's directory. + +## Module-specific configuration + +A Calamares module *may* read a module configuration file, +named `.conf`. If such a file is present in the module's directory, it is shipped as a *default* configuration file. -The module configuration file, if it exists, is a YAML 1.2 document which contains a YAML map of anything. -All default module configuration files are installed in `$DESTDIR/share/calamares/modules` but can be overridden by -files with the same name placed manually (or by the packager) in `/etc/calamares/modules`. +The module configuration file, if it exists, is a YAML 1.2 document +which contains a YAML map of anything. + +All default module configuration files are installed in +`$DESTDIR/share/calamares/modules` but can be overridden by +files with the same name placed manually (or by the packager) +in `/etc/calamares/modules`. -### Qt plugin viewmodules +## C++ modules -Currently the only way to write a module which exposes one or more installer pages (viewmodule) is through a Qt plugin. -Viewmodules should implement `Calamares::ViewStep`. They can also implement `Calamares::Job` to provide jobs. +Currently the recommended way to write a module which exposes one or more +installer pages (viewmodule) is through a C++ and Qt plugin. Viewmodules must +implement `Calamares::ViewStep`. They can also implement `Calamares::Job` +to provide jobs. -To add a Qt plugin module, put it in a subdirectory and make sure it has a `module.desc` and a `CMakeLists.txt` with a -`calamares_add_plugin` call. It will be picked up automatically by our CMake magic. +To add a Qt plugin module, put it in a subdirectory and make sure it has +a `CMakeLists.txt` with a `calamares_add_plugin` call. It will be picked +up automatically by our CMake magic. The `module.desc` file is optional. +## Python modules -### Python and process jobmodules +Modules may use one of the python interfaces, which may be present +in a Calamares installation (but also may not be). These modules must have +a `module.desc` file. The Python script must implement one or more of the +Python interfaces for Calamares -- either the python jobmodule interface, +or the experimental pythonqt job- and viewmodule interfaces. -Batch jobs for Calamares can be written as Python scripts or as generic commands (shell scripts, external programs, etc.). -To add a Python or process jobmodule, put it in a subdirectory and make sure it has a `module.desc`. -It will be picked up automatically by our CMake magic. +To add a Python or process jobmodule, put it in a subdirectory and make sure +it has a `module.desc`. It will be picked up automatically by our CMake magic. `CMakeLists.txt` is *not* used for Python and process jobmodules. -A Python jobmodule is a Python program which imports libcalamares and has a function `run()` as entry point. -`run()` must return `None` if everything went well, or a tuple `(str,str)` with an error message and description if -something went wrong. +Calamares offers a Python API for module developers, the core Calamares +functionality is exposed as `libcalamares.job` for job data, +`libcalamares.globalstorage` for shared data and `libcalamares.utils` for +generic utility functions. Documentation is inline. + +All code in Python job modules must obey PEP8, the only exception are +`libcalamares.globalstorage` keys, which should always be +camelCaseWithLowerCaseInitial to match the C++ identifier convention. + +For testing and debugging we provide the `testmodule.py` script which +fakes a limited Calamares Python environment for running a single jobmodule. + +### Python Jobmodule + +A Python jobmodule is a Python program which imports libcalamares and has a +function `run()` as entry point. The function `run()` must return `None` if +everything went well, or a tuple `(str,str)` with an error message and +description if something went wrong. + +### PythonQt Jobmodule + +A PythonQt jobmodule implements the experimental Job interface by defining +a subclass of something. + +### PythonQt Viewmodule + +A PythonQt viewmodule implements the experimental View interface by defining +a subclass of something. + +## Process jobmodules -Calamares offers a Python API for module developers, the core Calamares functionality is exposed as `libcalamares.job` -for job data, `libcalamares.globalstorage` for shared data and `libcalamares.utils` for generic utility functions. -Documentation is inline. +A process jobmodule runs a (single) command. The interface is "process", +while the module type must be "job" or "jobmodule". -All code in Python job modules must obey PEP8, the only exception are `libcalamares.globalstorage` keys, which should -always be camelCaseWithLowerCaseInitial. +The key *command* should have a string as value, which is passed to the +shell -- remember to quote it properly. -For testing and debugging we provide the `testmodule.py` script which fakes a limited Calamares Python environment for -running a single jobmodule. \ No newline at end of file diff --git a/src/modules/dracutlukscfg/module.desc b/src/modules/dracutlukscfg/module.desc deleted file mode 100644 index 10d9b78a9..000000000 --- a/src/modules/dracutlukscfg/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# Module metadata file for dracutlukscfg job -# Syntax is YAML 1.2 ---- -type: "job" -name: "dracutlukscfg" -interface: "qtplugin" -load: "libcalamares_job_dracutlukscfg.so" diff --git a/src/modules/dummycpp/module.desc b/src/modules/dummycpp/module.desc index 7f29e512e..11b9c500c 100644 --- a/src/modules/dummycpp/module.desc +++ b/src/modules/dummycpp/module.desc @@ -1,5 +1,18 @@ # Module metadata file for dummycpp job +# +# The metadata for C++ (qtplugin) plugins is almost never interesting: +# the CMakeLists.txt should be using calamares_add_plugin() which will +# generate the metadata file during the build. Only C++ plugins that +# have strange settings should have a module.desc (non-C++ plugins, +# on the other hand, must have one, since they don't have CMakeLists.txt). +# # Syntax is YAML 1.2 +# +# All four keys are mandatory. For C++ (qtplugin) modules, the interface +# value must be "qtplugin"; type is one of "job" or "view"; the name +# is the machine-identifier for the module and the load value should +# be the filename of the library that contains the implementation. +# --- type: "job" name: "dummycpp" diff --git a/src/modules/finished/module.desc b/src/modules/finished/module.desc deleted file mode 100644 index bc3e628c6..000000000 --- a/src/modules/finished/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# Module metadata file for greeting viewmodule -# Syntax is YAML 1.2 ---- -type: "view" #core or view -name: "finished" #the module name. must be unique and same as the parent directory -interface: "qtplugin" #can be: qtplugin, python, process, ... -load: "libcalamares_viewmodule_finished.so" diff --git a/src/modules/interactiveterminal/module.desc b/src/modules/interactiveterminal/module.desc deleted file mode 100644 index a2b5087c9..000000000 --- a/src/modules/interactiveterminal/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# Module metadata file for interactiveterminal viewmodule -# Syntax is YAML 1.2 ---- -type: "view" -name: "interactiveterminal" -interface: "qtplugin" -load: "libcalamares_viewmodule_interactiveterminal.so" diff --git a/src/modules/keyboard/module.desc b/src/modules/keyboard/module.desc deleted file mode 100644 index 391db19fc..000000000 --- a/src/modules/keyboard/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# Module metadata file for keyboard viewmodule -# Syntax is YAML 1.2 ---- -type: "view" -name: "keyboard" -interface: "qtplugin" -load: "libcalamares_viewmodule_keyboard.so" diff --git a/src/modules/license/module.desc b/src/modules/license/module.desc deleted file mode 100644 index 3c30ec3da..000000000 --- a/src/modules/license/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# Module metadata file for keyboard viewmodule -# Syntax is YAML 1.2 ---- -type: "view" -name: "license" -interface: "qtplugin" -load: "libcalamares_viewmodule_license.so" diff --git a/src/modules/locale/module.desc b/src/modules/locale/module.desc deleted file mode 100644 index d69fb5a1e..000000000 --- a/src/modules/locale/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# Module metadata file for locale viewmodule -# Syntax is YAML 1.2 ---- -type: "view" -name: "locale" -interface: "qtplugin" -load: "libcalamares_viewmodule_locale.so" diff --git a/src/modules/netinstall/module.desc b/src/modules/netinstall/module.desc deleted file mode 100644 index f39082eba..000000000 --- a/src/modules/netinstall/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# Module metadata file for netinstall module -# Syntax is YAML 1.2 ---- -type: "view" -name: "netinstall" -interface: "qtplugin" -load: "libcalamares_viewmodule_netinstall.so" diff --git a/src/modules/partition/module.desc b/src/modules/partition/module.desc deleted file mode 100644 index ba459e948..000000000 --- a/src/modules/partition/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# Module metadata file for partition viewmodule -# Syntax is YAML 1.2 ---- -type: "view" #core or view -name: "partition" #the module name. must be unique and same as the parent directory -interface: "qtplugin" #can be: qtplugin, python, process, ... -load: "libcalamares_viewmodule_partition.so" diff --git a/src/modules/summary/module.desc b/src/modules/summary/module.desc deleted file mode 100644 index 2fedbaabf..000000000 --- a/src/modules/summary/module.desc +++ /dev/null @@ -1,12 +0,0 @@ -# Module metadata file for summary viewmodule -# -# The summary module tells the user what is going to happen (next) -# during the installation. Each other step is responsible for -# creating a summary widget that this step can display. -# -# Syntax is YAML 1.2 ---- -type: "view" -name: "summary" -interface: "qtplugin" -load: "libcalamares_viewmodule_summary.so" diff --git a/src/modules/users/module.desc b/src/modules/users/module.desc deleted file mode 100644 index fd7b21b58..000000000 --- a/src/modules/users/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# Module metadata file for users viewmodule -# Syntax is YAML 1.2 ---- -type: "view" #core or view -name: "users" #the module name. must be unique and same as the parent directory -interface: "qtplugin" #can be: qtplugin, python, process, ... -load: "libcalamares_viewmodule_users.so" diff --git a/src/modules/webview/module.desc b/src/modules/webview/module.desc deleted file mode 100644 index 006198124..000000000 --- a/src/modules/webview/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# Module metadata file for welcome viewmodule -# Syntax is YAML 1.2 ---- -type: "view" #core or view -name: "webview" #the module name. must be unique and same as the parent directory -interface: "qtplugin" #can be: qtplugin, python, process, ... -load: "libcalamares_viewmodule_webview.so" diff --git a/src/modules/welcome/CMakeLists.txt b/src/modules/welcome/CMakeLists.txt index b087164fa..f901a768e 100644 --- a/src/modules/welcome/CMakeLists.txt +++ b/src/modules/welcome/CMakeLists.txt @@ -3,6 +3,8 @@ include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) find_package( LIBPARTED REQUIRED ) find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED DBus Network ) +include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) + set_source_files_properties( checker/partman_devices.c PROPERTIES LANGUAGE CXX ) set( CHECKER_SOURCES diff --git a/src/modules/welcome/module.desc b/src/modules/welcome/module.desc deleted file mode 100644 index 70383a55f..000000000 --- a/src/modules/welcome/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# Module metadata file for welcome viewmodule -# Syntax is YAML 1.2 ---- -type: "view" #core or view -name: "welcome" #the module name. must be unique and same as the parent directory -interface: "qtplugin" #can be: qtplugin, python, process, ... -load: "libcalamares_viewmodule_welcome.so"