diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..ce60bd6e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,273 @@ +name: CI +on: + push: + branches: + - master + tags: + - '*' + pull_request: + branches: + - master +jobs: + build-mex: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-20.04,windows-2019,macos-12,macos-14] + steps: + - name: Retrieve the source code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install MATLAB + uses: matlab-actions/setup-matlab@v2 + with: + release: ${{ matrix.os == 'macos-14' && 'R2023b' || ( matrix.os == 'windows-2019' && 'R2021b' || 'R2021a' ) }} + - name: Build MEX files + uses: matlab-actions/run-command@v2 + with: + command: "cd lib; mex cvx_eliminate_mex.c; mex cvx_bcompress_mex.c; cd ..; cvx_setup -exit-if" + - name: Upload MATLAB MEX files + uses: actions/upload-artifact@v4 + with: + name: mex-${{ matrix.os }} + path: "lib/*.mex*" + build-oct: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-20.04,windows-2019,macos-12,macos-14] + steps: + - name: Retrieve the source code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install Octave + shell: bash + run: | + if [ "${{ matrix.os }}" = ubuntu-20.04 ]; then + sudo apt update + sudo snap install octave + sudo apt install --no-install-recommends libopenblas-dev + echo "OCTAVE=snap run octave" >>$GITHUB_ENV + elif [ "${{ matrix.os }}" = windows-2019 ]; then + choco install octave.portable + else + brew install octave + echo "OCTAVE=octave" >>$GITHUB_ENV + fi + - name: Build MEX files (Unix) + if: matrix.os != 'windows-2019' + run: $OCTAVE --eval "cd lib; mex cvx_eliminate_mex.c; mex cvx_bcompress_mex.c" + - name: Build Mex files (Windows) + if: matrix.os == 'windows-2019' + shell: cmd + run: | + set PATH=C:\ProgramData\chocolatey\bin;%PATH% + octave-cli.exe --no-gui --eval "cd lib; mex cvx_eliminate_mex.c; mex cvx_bcompress_mex.c" + if %errorlevel% neq 0 exit /b %errorlevel% + - name: Upload Octave MEX files + uses: actions/upload-artifact@v4 + with: + name: oct-${{ matrix.os }} + path: "lib/*.mex" + package: + needs: [build-mex,build-oct] + runs-on: ubuntu-latest + steps: + - name: Retrieve the source code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Compile the docs + run: | + sudo apt update + sudo apt install latexmk texlive-latex-recommended texlive-latex-extra tex-gyre make + source $CONDA/bin/activate + conda install -c defaults -c conda-forge sphinx cloud_sptheme + pushd doc + sphinx-build -b latex -d _build/doctrees . _build/latex + sphinx-build -b html -d _build/doctrees . _build/html + pushd _build/latex + latexmk -pdf CVX.tex + popd + popd + mv doc _doc + mkdir doc + mv _doc/_build/{html,latex/CVX.pdf} doc/ + rm -rf _doc + - name: Extract version info + run: | + /bin/echo -n Extracting and updating version information... + DESCR=$(git describe --long) + VERSION=$(echo "$DESCR" | cut -d '-' -f 1) + BUILD=$(echo "$DESCR" | cut -d '-' -f 2) + BCOMMIT=$(echo "$DESCR" | cut -d '-' -f 3 | sed 's@^g@@') + BDATE=$(git log -n1 --pretty=%ad --date=local) + MONTH=`date +%B` + MONBIB=`date +%b | tr [:upper:] [:lower:]` + YEAR=`date +%Y` + echo done. + echo "Version $DESCR, $MONTH $YEAR" + sed "s@cvx_bld *= *'[^']*'@cvx_bld = '$BUILD'@;s@cvx_bdate *= *'[^']*'@cvx_bdate = '$BDATE'@;s@cvx_bcomm *= *'[^']*'@cvx_bcomm = '$BCOMMIT'@" cvx_version.m > cvx_version.new + mv -f cvx_version.new cvx_version.m + - name: Retrieve artifacts + uses: actions/download-artifact@v4 + - name: Move artifacts into place + run: | + mkdir -p lib/o_lin && mv oct-ubuntu-*/* lib/o_lin/ + mkdir -p lib/o_win && mv oct-windows-*/* lib/o_win/ + mkdir -p lib/o_maci && mv oct-macos-12/* lib/o_maci/ + mkdir -p lib/o_maca && mv oct-macos-14/* lib/o_maca/ + mv mex-*/* lib/ + rmdir mex-* oct-* + - name: Download solvers + run: | + rm -rf sdpt3 sedumi || : + for url in $(grep -v ^# solvers.txt); do + echo "Downloading: $url" + curl -OL $url + fname=${url##*/} + echo "Unpacking: $fname" + tar xfz $fname + rm $fname + done + rm -rf solvers.txt .gitignore .git .github */.gitignore + - name: Show files, build archives + run: | + GCOM="^\.\\|^doc/\\|^examples/" + find . -type d | sed 's@^\./\(.*\)@\1/@' | grep -v $GCOM | sort -f >MANIFEST + find . \! -type d | sed 's@^\./@@' | grep -v $GCOM | sort -f >>MANIFEST + cd .. + mv CVX cvx + zip -r cvx.zip cvx + tar cfz cvx.tgz cvx + echo "--------" + tar tfz cvx.tgz + echo "--------" + zipinfo cvx.zip + echo "--------" + mv cvx CVX + mv cvx.tgz cvx.zip CVX + - name: Upload bundles + uses: actions/upload-artifact@v4 + with: + name: bundles + path: | + cvx.zip + cvx.tgz + matlab-tests: + needs: package + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest,macos-latest,windows-latest,macos-14] + steps: + - name: Retrieve artifact + uses: actions/download-artifact@v4 + with: + name: bundles + - name: Unpack artifact + shell: bash + run: | + tar xfz cvx.tgz --strip-components=1 + rm cvx.tgz cvx.zip + - name: Install latest MATLAB + uses: matlab-actions/setup-matlab@v2 + - name: Run test + uses: matlab-actions/run-command@v2 + with: + command: "cvx_setup -exit-if" + octave-tests: + needs: package + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest,windows-latest,macos-latest,macos-14] + steps: + - name: Retrieve artifact + uses: actions/download-artifact@v4 + with: + name: bundles + - name: Unpack artifact + shell: bash + run: | + tar xfz cvx.tgz --strip-components=1 + rm cvx.tgz cvx.zip + - name: Install Octave, Snap, Flatpak + shell: bash + run: | + if [ "${{ matrix.os }}" = ubuntu-latest ]; then + sudo apt update + sudo apt install --no-install-recommends octave + elif [ "${{ matrix.os }}" = windows-latest ]; then + choco install octave.portable + else + brew install octave + fi + - name: Run test (Unix) + shell: bash + run: octave --eval "cvx_setup -exit-if" + - name: Run test (Windows) + if: matrix.os == 'windows-latest' + shell: cmd + run: | + set PATH=C:\ProgramData\chocolatey\bin;%PATH% + octave-cli.exe --no-gui --eval "cvx_setup -exit-if" + flatpak-test: + needs: package + runs-on: ubuntu-latest + steps: + - name: Retrieve artifact + uses: actions/download-artifact@v4 + with: + name: bundles + - name: Unpack artifact + run: | + tar xfz cvx.tgz --strip-components=1 + rm cvx.tgz cvx.zip + - name: Install Flatpak octave + run: | + sudo apt update + sudo apt install flatpak + flatpak remote-add --user --if-not-exists \ + flathub https://flathub.org/repo/flathub.flatpakrepo + flatpak install --user -y flathub org.octave.Octave + - name: Run test + shell: bash + run: flatpak run org.octave.Octave --eval "cvx_setup -exit-if" + snap-test: + needs: package + runs-on: ubuntu-latest + steps: + - name: Retrieve artifact + uses: actions/download-artifact@v4 + with: + name: bundles + - name: Unpack artifact + run: | + tar xfz cvx.tgz --strip-components=1 + rm cvx.tgz cvx.zip + - name: Install Flatpak octave + run: | + sudo snap install octave + - name: Run test + shell: bash + run: snap run octave --eval "cvx_setup -exit-if" + publish: + needs: [matlab-tests,octave-tests,flatpak-test,snap-test] + if: startsWith(github.ref, 'refs/tags/') + runs-on: ubuntu-latest + steps: + - name: Retrieve artifacts + uses: actions/download-artifact@v4 + with: + name: bundles + - uses: softprops/action-gh-release@v2 + with: + files: | + cvx.tgz + cvx.zip \ No newline at end of file diff --git a/.gitignore b/.gitignore index f6d04ee1..5beac4c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,10 @@ doc/_build +sedumi/ +sdpt3/ +sedumi.tgz +sedumi.zip +sdpt3.tgz +sdpt3.zip +lib/*.mex* +lib/*/*.mex diff --git a/.gitmodules b/.gitmodules index 607e8293..e69de29b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +0,0 @@ -[submodule "sedumi"] - path = sedumi - url = git@github.com:sqlp/sedumi.git - branch = pretransfo -[submodule "sdpt3"] - path = sdpt3 - url = git@github.com:sqlp/sdpt3.git diff --git a/README.md b/README.md index ae7564e2..7ac32eb9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,27 @@ ## CVX: A system for disciplined convex programming +#### [Click here](https://github.com/cvxr/cvx/releases/latest) to download the precompiled bundle from this repository. These bundles include the SeDuMi and SDPT3 solvers, as well as pre-compiled MATLAB and Octave MEX files files for Windows, Linux, and macOS (Intel and Apple Silicon). + +### IMPORTANT UPDATE + +We are working towards making this repository the *official* source +for CVX, and updating the [download page](http://cvxr.com/cvx/download) +with links back to this site. This will take a bit more time; but when +finished, there will be significant benefits: + +- Fresh builds of the supporting MEX files for Linux, Windows, macOS + Apple Silicon, and macOS Intel will be included. +- The solver shims for Mosek and Gurobi will be included, without + obfuscation, so that anyone with a valid license for these solvers + can use CVX, for commercial and non-commercial use. +- We will be able to slowly enable community contributions to supply + bug fixes and improvements. Note that the first of these improvements + will need to include improvements to an automatable test suite to + help insure that changes do not introduce regressions. + +Please stay tuned, here and on the [web site](http://cvxr.com/cvx), +for further developments. + ### Introduction CVX is a Matlab package for convex optimizaton. diff --git a/cvx_setup.m b/cvx_setup.m index 1645a530..361fc9bb 100644 --- a/cvx_setup.m +++ b/cvx_setup.m @@ -19,6 +19,7 @@ function cvx_setup( varargin ) cvx_version( '-install', varargin{:} ); if ~isfield( cvx___, 'loaded' ) || ~cvx___.loaded, %#ok + if cvx___.exit_if, exit(-1); end error( 'CVX:Expected', 'Error detected by cvx_version' ); end isoctave = cvx___.isoctave; @@ -151,6 +152,7 @@ function cvx_setup( varargin ) 'No valid solvers were found. This suggests a corrupt installation. Please\n', ... 'try re-installing the files and re-running cvx_setup. If the same error\n', ... 'occurs, please contact CVX support.\n' ] ); + if cvx___.exit_if, exit(-1); end error('CVX:Unexpected','No valid solvers were found.'); end solvers = solvers(cellfun(@isempty,{solvers.error})); @@ -179,6 +181,7 @@ function cvx_setup( varargin ) cvx_global; if isempty( cvx___.solvers.list ), + if cvx___.exit_if, exit(-1); end error('CVX:Unexpected','No valid solvers were found.'); end diff --git a/cvx_version.m b/cvx_version.m index e776fb68..cb2a3def 100644 --- a/cvx_version.m +++ b/cvx_version.m @@ -12,6 +12,7 @@ args = varargin; compile = false; +exit_if = false; quick = nargout > 0; if nargin if ~ischar( args{1} ), @@ -23,9 +24,13 @@ tt = strcmp( args, '-compile' ); compile = any( tt ); if compile, quick = false; args(tt) = []; end + tt = strcmp( args, '-exit-if' ); + exit_if = any( tt ); + if exit_if, quick = false; args(tt) = []; end end end +cvx___.exit_if = exit_if; if isfield( cvx___, 'loaded' ), if quick, return; end @@ -39,32 +44,25 @@ isoctave = exist( 'OCTAVE_VERSION', 'builtin' ); % File and path separators, MEX extension + comp = computer; if isoctave, - comp = octave_config_info('canonical_host_type'); mext = 'mex'; izpc = false; izmac = false; - if octave_config_info('mac'), - msub = 'mac'; - izmac = true; - elseif octave_config_info('windows'), - msub = 'win'; - izpc = true; - elseif octave_config_info('unix') && any(strfind(comp,'linux')), - msub = 'lin'; - else - msub = 'unknown'; - end - if ~isempty( msub ), - msub = [ 'o_', msub ]; - if strncmp( comp, 'x86_64', 6 ), - msub = [ msub, '64' ]; - else - msub = [ msub, '32' ]; - end + switch comp + case 'x86_64-pc-linux-gnu' + msub = 'o_lin'; + case 'x86_64-apple-darwin21.6.0' + msub = 'o_maci'; + case 'aarch64-apple-darwin23.4.0' + msub = 'o_maca'; + case 'x86_64-w64-mingw32' + msub = 'o_win'; + otherwise + warning(sprintf('Unexpected Octave computer type: %s', COMPUTER)); + msub = ''; end else - comp = computer; izpc = strncmp( comp, 'PC', 2 ); izmac = strncmp( comp, 'MAC', 3 ); mext = mexext; @@ -143,7 +141,7 @@ line = '---------------------------------------------------------------------------'; fprintf( '\n%s\n', line ); fprintf( 'CVX: Software for Disciplined Convex Programming (c)2014 CVX Research\n' ); -fprintf( 'Version %3s, Build %4s (%7s)%42s\n', cvx_ver, cvx_bld, cvx_bcomm, cvx_bdate ); +fprintf( 'Version %3s, Build %3s (%7s)%42s\n', cvx_ver, cvx_bld, cvx_bcomm, cvx_bdate ); fprintf( '%s\n', line ); fprintf( 'Installation info:\n Path: %s\n', cvx___.where ); if isoctave, @@ -317,6 +315,8 @@ if ~issue, cvx___.loaded = true; +elseif exit_if, + exit(1) end clear fs; fprintf( '%s\n', line ); diff --git a/doc/conf.py b/doc/conf.py index 76226910..d57cf47e 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -116,7 +116,7 @@ # The name of an image file (relative to this directory) to place at the top # of the sidebar. -html_logo = 'cvxrlogo.png' +html_logo = '_static/cvxrlogo.png' # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 @@ -178,7 +178,7 @@ latex_elements = { 'papersize': 'letterpaper', 'pointsize': '11pt', - 'preamble': '\usepackage{amsmath,amssymb}', + 'preamble': r'\usepackage{amsmath,amssymb}', } # Grouping the document tree into LaTeX files. List of tuples diff --git a/lib/cvx_bcompress_mex.mexa64 b/lib/cvx_bcompress_mex.mexa64 deleted file mode 100755 index b5d95e69..00000000 Binary files a/lib/cvx_bcompress_mex.mexa64 and /dev/null differ diff --git a/lib/cvx_bcompress_mex.mexglx b/lib/cvx_bcompress_mex.mexglx deleted file mode 100644 index 82721079..00000000 Binary files a/lib/cvx_bcompress_mex.mexglx and /dev/null differ diff --git a/lib/cvx_bcompress_mex.mexmaci64 b/lib/cvx_bcompress_mex.mexmaci64 deleted file mode 100755 index 16422a5b..00000000 Binary files a/lib/cvx_bcompress_mex.mexmaci64 and /dev/null differ diff --git a/lib/cvx_bcompress_mex.mexw64 b/lib/cvx_bcompress_mex.mexw64 deleted file mode 100644 index 483c422c..00000000 Binary files a/lib/cvx_bcompress_mex.mexw64 and /dev/null differ diff --git a/lib/cvx_eliminate_mex.mexa64 b/lib/cvx_eliminate_mex.mexa64 deleted file mode 100755 index 4803f072..00000000 Binary files a/lib/cvx_eliminate_mex.mexa64 and /dev/null differ diff --git a/lib/cvx_eliminate_mex.mexglx b/lib/cvx_eliminate_mex.mexglx deleted file mode 100755 index c15dda3b..00000000 Binary files a/lib/cvx_eliminate_mex.mexglx and /dev/null differ diff --git a/lib/cvx_eliminate_mex.mexmaci64 b/lib/cvx_eliminate_mex.mexmaci64 deleted file mode 100755 index 2278e95a..00000000 Binary files a/lib/cvx_eliminate_mex.mexmaci64 and /dev/null differ diff --git a/lib/cvx_eliminate_mex.mexw64 b/lib/cvx_eliminate_mex.mexw64 deleted file mode 100644 index 546d2ebd..00000000 Binary files a/lib/cvx_eliminate_mex.mexw64 and /dev/null differ diff --git a/lib/o_lin64/cvx_bcompress_mex.mex b/lib/o_lin64/cvx_bcompress_mex.mex deleted file mode 100755 index 3ba0a322..00000000 Binary files a/lib/o_lin64/cvx_bcompress_mex.mex and /dev/null differ diff --git a/lib/o_lin64/cvx_eliminate_mex.mex b/lib/o_lin64/cvx_eliminate_mex.mex deleted file mode 100755 index 1bd03970..00000000 Binary files a/lib/o_lin64/cvx_eliminate_mex.mex and /dev/null differ diff --git a/lib/o_mac64/cvx_bcompress_mex.mex b/lib/o_mac64/cvx_bcompress_mex.mex deleted file mode 100755 index edd98e2b..00000000 Binary files a/lib/o_mac64/cvx_bcompress_mex.mex and /dev/null differ diff --git a/lib/o_mac64/cvx_eliminate_mex.mex b/lib/o_mac64/cvx_eliminate_mex.mex deleted file mode 100755 index 83500325..00000000 Binary files a/lib/o_mac64/cvx_eliminate_mex.mex and /dev/null differ diff --git a/sdpt3 b/sdpt3 deleted file mode 160000 index 3b880163..00000000 --- a/sdpt3 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3b880163eba732c396a1a346dac4a350a259249a diff --git a/sedumi b/sedumi deleted file mode 160000 index e422895d..00000000 --- a/sedumi +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e422895d47992b2f89b3f69b59bb78834fc923fa diff --git a/solvers.txt b/solvers.txt new file mode 100644 index 00000000..59daab2a --- /dev/null +++ b/solvers.txt @@ -0,0 +1,5 @@ +# These are the URLs of the SDPT3 and SeDuMi bundles to include. +# We have stopped using submodules because the MEX files are no +# longer checked into Git; instead, they are built by CI processes +https://github.com/sqlp/sedumi/releases/download/v1.3.8/sedumi.tgz +https://github.com/sqlp/sdpt3/releases/download/4.0-20240410/sdpt3.tgz