From b18ee398ed047e9503fec69784683ad2b0ab7009 Mon Sep 17 00:00:00 2001 From: Winlin Date: Sun, 20 Nov 2022 15:02:08 +0800 Subject: [PATCH] Windows: Support cygwin pipline and packager. v5.0.89 (#3257) 1. Support github actions on Windows Server 2022. 2. Use cygwin64 in windows-latest to build SRS. 3. Package SRS-xxx-setup.exe by NSIS.exe 4. Patch crypto/include/config.h for libsrtp. 5. Support run as administrator. 6. Apply utest for cygwin. 7. Enable srtp over openssl. --- .github/workflows/release.yml | 240 ++++++++++++++---- .github/workflows/test.yml | 59 +++++ .gitignore | 1 + .../srtp/cygwin-crypto-include-config.h | 194 ++++++++++++++ .../srtp/cygwin-gcm-crypto-include-config.h | 194 ++++++++++++++ trunk/auto/depends.sh | 9 + trunk/auto/options.sh | 6 - trunk/doc/CHANGELOG.md | 1 + trunk/doc/Features.md | 1 + trunk/doc/srs-logo.ico | Bin 0 -> 44798 bytes trunk/packaging/nsis/srs-cli.bat | 11 + trunk/packaging/nsis/srs-live.bat | 11 + trunk/packaging/nsis/srs-rtc.bat | 11 + trunk/packaging/nsis/srs.nsi | 154 +++++++++++ trunk/packaging/nsis/srs.pid | 0 trunk/src/core/srs_core_version5.hpp | 2 +- 16 files changed, 834 insertions(+), 60 deletions(-) create mode 100644 trunk/3rdparty/patches/srtp/cygwin-crypto-include-config.h create mode 100644 trunk/3rdparty/patches/srtp/cygwin-gcm-crypto-include-config.h create mode 100644 trunk/doc/srs-logo.ico create mode 100644 trunk/packaging/nsis/srs-cli.bat create mode 100644 trunk/packaging/nsis/srs-live.bat create mode 100644 trunk/packaging/nsis/srs-rtc.bat create mode 100644 trunk/packaging/nsis/srs.nsi create mode 100644 trunk/packaging/nsis/srs.pid diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3a075ef80..7271f8d9a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -64,6 +64,165 @@ jobs: run: | docker run --rm srs:test bash -c 'make && ./objs/srs -c conf/regression-test.conf && \ cd 3rdparty/srs-bench && make && ./objs/srs_test -test.v' + outputs: + SRS_TEST_DONE: ok + + draft: + name: draft + runs-on: ubuntu-20.04 + needs: + - envs + steps: + - name: Create release draft + id: create_draft + uses: ncipollo/release-action@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + allowUpdates: true + tag: ${{ github.ref }} + draft: true + prerelease: true + outputs: + SRS_RELEASE_ID: ${{ steps.create_draft.outputs.id }} + + cygwin64: + name: cygwin64 + runs-on: windows-latest + needs: + - envs + - draft + steps: + # See https://github.com/cygwin/cygwin-install-action#parameters + # Note that https://github.com/egor-tensin/setup-cygwin fails to install packages. + - name: Setup Cygwin + uses: cygwin/cygwin-install-action@master + with: + platform: x86_64 + packages: bash make gcc-g++ cmake automake patch pkg-config tcl + install-dir: C:\cygwin64 + ################################################################################################################## + - name: Checkout repository + uses: actions/checkout@v2 + ################################################################################################################## + - name: Covert output to env + env: + SHELLOPTS: igncr + shell: C:\cygwin64\bin\bash.exe --login '{0}' + run: | + echo "SRS_TAG=${{ needs.envs.outputs.SRS_TAG }}" >> $GITHUB_ENV + echo "SRS_VERSION=${{ needs.envs.outputs.SRS_VERSION }}" >> $GITHUB_ENV + echo "SRS_MAJOR=${{ needs.envs.outputs.SRS_MAJOR }}" >> $GITHUB_ENV + echo "SRS_RELEASE_ID=${{ needs.draft.outputs.SRS_RELEASE_ID }}" >> $GITHUB_ENV + ################################################################################################################## + - name: Build SRS + env: + SHELLOPTS: igncr + SRS_WORKSPACE: ${{ github.workspace }} + shell: C:\cygwin64\bin\bash.exe --login '{0}' + run: | + export PATH=/usr/bin:/usr/local/bin && + which make gcc g++ patch cmake pkg-config uname grep sed && + (make --version; gcc --version; patch --version; cmake --version; pkg-config --version) && + (aclocal --version; autoconf --version; automake --version; uname -a) && + cd $(cygpath -u $SRS_WORKSPACE)/trunk && ./configure && make + ################################################################################################################## + - name: Package SRS + env: + SHELLOPTS: igncr + SRS_WORKSPACE: ${{ github.workspace }} + shell: C:\cygwin64\bin\bash.exe --login '{0}' + run: | + cd $(cygpath -u $SRS_WORKSPACE) && + if [[ $(echo $SRS_TAG |grep -qE '^v' && echo YES) != YES ]]; then + SRS_VERSION=$(./trunk/objs/srs -v 2>&1); echo "Change version to ${SRS_VERSION}"; + fi && + "/cygdrive/c/Program Files (x86)/NSIS/makensis.exe" /DSRS_VERSION=${SRS_VERSION} \ + /DCYGWIN_DIR="C:\cygwin64" trunk/packaging/nsis/srs.nsi && + mv trunk/packaging/nsis/SRS-Windows-x86_64-${SRS_VERSION}-setup.exe . && ls -lh *.exe && + echo "SRS_CYGWIN_TAR=SRS-Windows-x86_64-${SRS_VERSION}-setup.exe" >> $GITHUB_ENV && + echo "SRS_CYGWIN_MD5=$(md5sum SRS-Windows-x86_64-${SRS_VERSION}-setup.exe| awk '{print $1}')" >> $GITHUB_ENV + ################################################################################################################## + - name: Upload Release Assets Cygwin + id: upload-release-assets-cygwin + uses: dwenegar/upload-release-assets@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + release_id: ${{ env.SRS_RELEASE_ID }} + assets_path: ${{ env.SRS_CYGWIN_TAR }} + outputs: + SRS_CYGWIN_TAR: ${{ env.SRS_CYGWIN_TAR }} + SRS_CYGWIN_MD5: ${{ env.SRS_CYGWIN_MD5 }} + + linux: + name: linux + runs-on: ubuntu-20.04 + needs: + - envs + - draft + steps: + ################################################################################################################## + - name: Covert output to env + run: | + echo "SRS_TAG=${{ needs.envs.outputs.SRS_TAG }}" >> $GITHUB_ENV + echo "SRS_VERSION=${{ needs.envs.outputs.SRS_VERSION }}" >> $GITHUB_ENV + echo "SRS_MAJOR=${{ needs.envs.outputs.SRS_MAJOR }}" >> $GITHUB_ENV + echo "SRS_RELEASE_ID=${{ needs.draft.outputs.SRS_RELEASE_ID }}" >> $GITHUB_ENV + ################################################################################################################## + # Git checkout + - name: Checkout repository + uses: actions/checkout@v2 + ################################################################################################################## + # Create source tar for release. Note that it's for OpenWRT package srs-server, so the filename MUST be + # srs-server-xxx.tar.gz, because the package is named srs-server. + # Generate variables like: + # SRS_SOURCE_TAR=srs-server-5.0.145.tar.gz + # SRS_SOURCE_MD5=83e38700a80a26e30b2df054e69956e5 + - name: Create source tar.gz + run: | + DEST_DIR=srs-server-$SRS_VERSION && mkdir -p $DEST_DIR && + cp README.md $DEST_DIR && cp LICENSE $DEST_DIR && cp -R trunk $DEST_DIR/trunk && + (cd $DEST_DIR/trunk/3rdparty && rm -rf *.zip openssl-*.gz srs-bench) && + tar zcf ${DEST_DIR}.tar.gz ${DEST_DIR} && du -sh ${DEST_DIR}* && rm -rf ${DEST_DIR} && + echo "SRS_SOURCE_TAR=${DEST_DIR}.tar.gz" >> $GITHUB_ENV && + echo "SRS_SOURCE_MD5=$(md5sum ${DEST_DIR}.tar.gz| awk '{print $1}')" >> $GITHUB_ENV + # Create package tar for release + # Generate variables like: + # SRS_PACKAGE_ZIP=SRS-CentOS7-x86_64-5.0.145.zip + # SRS_PACKAGE_MD5=3880a26e30b283edf05700a4e69956e5 + - name: Create package zip + env: + PACKAGER: ${{ secrets.SRS_PACKAGER_BINARY }} + run: | + docker build --tag srs:pkg --build-arg version=$SRS_VERSION --build-arg SRS_AUTO_PACKAGER=$PACKAGER -f trunk/Dockerfile.pkg . && + SRS_PACKAGE_ZIP=SRS-CentOS7-x86_64-$SRS_VERSION.zip && + docker run --rm -v $(pwd):/output srs:pkg cp objs/$SRS_PACKAGE_ZIP /output/ && + du -sh $SRS_PACKAGE_ZIP && + echo "SRS_PACKAGE_ZIP=$SRS_PACKAGE_ZIP" >> $GITHUB_ENV && + echo "SRS_PACKAGE_MD5=$(md5sum $SRS_PACKAGE_ZIP| awk '{print $1}')" >> $GITHUB_ENV + ################################################################################################################## + - name: Upload Release Assets Packager + id: upload-release-assets-packager + uses: dwenegar/upload-release-assets@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + release_id: ${{ env.SRS_RELEASE_ID }} + assets_path: ${{ env.SRS_PACKAGE_ZIP }} + - name: Upload Release Assets Source + id: upload-release-assets-source + uses: dwenegar/upload-release-assets@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + release_id: ${{ env.SRS_RELEASE_ID }} + assets_path: ${{ env.SRS_SOURCE_TAR }} + outputs: + SRS_PACKAGE_ZIP: ${{ env.SRS_PACKAGE_ZIP }} + SRS_PACKAGE_MD5: ${{ env.SRS_PACKAGE_MD5 }} + SRS_SOURCE_TAR: ${{ env.SRS_SOURCE_TAR }} + SRS_SOURCE_MD5: ${{ env.SRS_SOURCE_MD5 }} docker-srs: name: docker-srs @@ -113,6 +272,8 @@ jobs: ossrs/srs:${{ env.SRS_VERSION }} ossrs/srs:${{ env.SRS_MAJOR }} ossrs/srs:v${{ env.SRS_MAJOR }} + outputs: + SRS_DOCKER_DONE: ok aliyun-srs: name: aliyun-srs @@ -144,6 +305,8 @@ jobs: registry.cn-hangzhou.aliyuncs.com/ossrs/srs:${{ env.SRS_VERSION }} registry.cn-hangzhou.aliyuncs.com/ossrs/srs:${{ env.SRS_MAJOR }} registry.cn-hangzhou.aliyuncs.com/ossrs/srs:v${{ env.SRS_MAJOR }} + outputs: + SRS_ALIYUN_DONE: ok update: name: update @@ -209,13 +372,18 @@ jobs: docker rmi -f $image echo "Remove image $image, r0=$?" done + outputs: + SRS_UPDATE_DONE: ok release: name: release runs-on: ubuntu-20.04 needs: - - update + #- update - envs + - draft + - cygwin64 + - linux steps: ################################################################################################################## - name: Covert output to env @@ -223,54 +391,37 @@ jobs: echo "SRS_TAG=${{ needs.envs.outputs.SRS_TAG }}" >> $GITHUB_ENV echo "SRS_VERSION=${{ needs.envs.outputs.SRS_VERSION }}" >> $GITHUB_ENV echo "SRS_MAJOR=${{ needs.envs.outputs.SRS_MAJOR }}" >> $GITHUB_ENV + echo "SRS_RELEASE_ID=${{ needs.draft.outputs.SRS_RELEASE_ID }}" >> $GITHUB_ENV + echo "SRS_PACKAGE_ZIP=${{ needs.linux.outputs.SRS_PACKAGE_ZIP }}" >> $GITHUB_ENV + echo "SRS_PACKAGE_MD5=${{ needs.linux.outputs.SRS_PACKAGE_MD5 }}" >> $GITHUB_ENV + echo "SRS_SOURCE_TAR=${{ needs.linux.outputs.SRS_SOURCE_TAR }}" >> $GITHUB_ENV + echo "SRS_SOURCE_MD5=${{ needs.linux.outputs.SRS_SOURCE_MD5 }}" >> $GITHUB_ENV + echo "SRS_CYGWIN_TAR=${{ needs.cygwin64.outputs.SRS_CYGWIN_TAR }}" >> $GITHUB_ENV + echo "SRS_CYGWIN_MD5=${{ needs.cygwin64.outputs.SRS_CYGWIN_MD5 }}" >> $GITHUB_ENV ################################################################################################################## # Git checkout - name: Checkout repository uses: actions/checkout@v2 - ################################################################################################################## - # Create source tar for release. Note that it's for OpenWRT package srs-server, so the filename MUST be - # srs-server-xxx.tar.gz, because the package is named srs-server. - # Generate variables like: - # SRS_SOURCE_TAR=srs-server-5.0.145.tar.gz - # SRS_SOURCE_MD5=83e38700a80a26e30b2df054e69956e5 - - name: Create source tar.gz - run: | - DEST_DIR=srs-server-$SRS_VERSION && mkdir -p $DEST_DIR && - cp README.md $DEST_DIR && cp LICENSE $DEST_DIR && cp -R trunk $DEST_DIR/trunk && - (cd $DEST_DIR/trunk/3rdparty && rm -rf *.zip openssl-*.gz srs-bench) && - tar zcf ${DEST_DIR}.tar.gz ${DEST_DIR} && du -sh ${DEST_DIR}* && rm -rf ${DEST_DIR} && - echo "SRS_SOURCE_TAR=${DEST_DIR}.tar.gz" >> $GITHUB_ENV && - echo "SRS_SOURCE_MD5=$(md5sum ${DEST_DIR}.tar.gz| awk '{print $1}')" >> $GITHUB_ENV - # Create package tar for release - # Generate variables like: - # SRS_PACKAGE_ZIP=SRS-CentOS7-x86_64-5.0.145.zip - # SRS_PACKAGE_MD5=3880a26e30b283edf05700a4e69956e5 - - name: Create package zip - env: - PACKAGER: ${{ secrets.SRS_PACKAGER_BINARY }} - run: | - docker build --tag srs:pkg --build-arg version=$SRS_VERSION --build-arg SRS_AUTO_PACKAGER=$PACKAGER -f trunk/Dockerfile.pkg . && - SRS_PACKAGE_ZIP=SRS-CentOS7-x86_64-$SRS_VERSION.zip && - docker run --rm -v $(pwd):/output srs:pkg cp objs/$SRS_PACKAGE_ZIP /output/ && - du -sh $SRS_PACKAGE_ZIP && - echo "SRS_PACKAGE_ZIP=$SRS_PACKAGE_ZIP" >> $GITHUB_ENV && - echo "SRS_PACKAGE_MD5=$(md5sum $SRS_PACKAGE_ZIP| awk '{print $1}')" >> $GITHUB_ENV # Create release. # TODO: FIXME: Refine the release when 5.0 released # TODO: FIXME: Change prerelease to false when 5.0 released - - name: Create release - id: create_release - uses: actions/create-release@v1 + - name: Update release + id: update_release + uses: ncipollo/release-action@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - tag_name: ${{ github.ref }} - release_name: Release ${{ github.ref }} + allowUpdates: true + tag: ${{ github.ref }} + name: Release ${{ env.SRS_TAG }} body: | - [${{ github.event.head_commit.message }}](https://github.com/ossrs/srs/commit/${{ github.sha }}) + [${{ github.sha }}](https://github.com/ossrs/srs/commit/${{ github.sha }}) + ${{ github.event.head_commit.message }} + ## Resource * Source: ${{ env.SRS_SOURCE_MD5 }} [${{ env.SRS_SOURCE_TAR }}](https://github.com/ossrs/srs/releases/download/${{ env.SRS_TAG }}/${{ env.SRS_SOURCE_TAR }}) * Binary: ${{ env.SRS_PACKAGE_MD5 }} [${{ env.SRS_PACKAGE_ZIP }}](https://github.com/ossrs/srs/releases/download/${{ env.SRS_TAG }}/${{ env.SRS_PACKAGE_ZIP }}) + * Binary: ${{ env.SRS_CYGWIN_MD5 }} [${{ env.SRS_CYGWIN_TAR }}](https://github.com/ossrs/srs/releases/download/${{ env.SRS_TAG }}/${{ env.SRS_CYGWIN_TAR }}) ## Docker * China: [docker pull registry.cn-hangzhou.aliyuncs.com/ossrs/srs:${{ env.SRS_MAJOR }}](https://ossrs.net/lts/zh-cn/docs/v5/doc/getting-started) * China: [docker pull registry.cn-hangzhou.aliyuncs.com/ossrs/srs:${{ env.SRS_TAG }}](https://ossrs.net/lts/zh-cn/docs/v5/doc/getting-started) @@ -282,29 +433,12 @@ jobs: * [中文FAQ](https://ossrs.net/lts/zh-cn/faq) or [FAQ](https://ossrs.io/lts/en-us/faq), [Features](https://github.com/ossrs/srs/blob/${{ github.sha }}/trunk/doc/Features.md#features) or [ChangeLogs](https://github.com/ossrs/srs/blob/${{ github.sha }}/trunk/doc/CHANGELOG.md#changelog) draft: false prerelease: true - # Upload release source files - - name: Upload Release Assets Source - id: upload-release-assets-source - uses: dwenegar/upload-release-assets@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - release_id: ${{ steps.create_release.outputs.id }} - assets_path: ${{ env.SRS_SOURCE_TAR }} - # Upload release package files - - name: Upload Release Assets Package - id: upload-release-assets-package - uses: dwenegar/upload-release-assets@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - release_id: ${{ steps.create_release.outputs.id }} - assets_path: ${{ env.SRS_PACKAGE_ZIP }} done: name: done runs-on: ubuntu-20.04 needs: + - update - release steps: - run: echo 'All done' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 182d72726..ebcfdb256 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,6 +4,34 @@ name: "Test" on: [push, pull_request] jobs: + cygwin64: + name: cygwin64 + runs-on: windows-latest + steps: + # See https://github.com/cygwin/cygwin-install-action#parameters + # Note that https://github.com/egor-tensin/setup-cygwin fails to install packages. + - name: Setup Cygwin + uses: cygwin/cygwin-install-action@master + with: + platform: x86_64 + packages: bash make gcc-g++ cmake automake patch pkg-config tcl + install-dir: C:\cygwin64 + ################################################################################################################## + - name: Checkout repository + uses: actions/checkout@v2 + ################################################################################################################## + - name: Build and test SRS + env: + SHELLOPTS: igncr + SRS_WORKSPACE: ${{ github.workspace }} + shell: C:\cygwin64\bin\bash.exe --login '{0}' + run: | + export PATH=/usr/bin:/usr/local/bin && + cd $(cygpath -u $SRS_WORKSPACE)/trunk && ./configure --utest=on && make utest && + ./objs/srs_utest + outputs: + SRS_CYGWIN_DONE: ok + build-centos7: name: build-centos7 runs-on: ubuntu-20.04 @@ -23,6 +51,8 @@ jobs: run: DOCKER_BUILDKIT=1 docker build -f trunk/Dockerfile.builds --target centos7-no-asm . - name: Build on CentOS7, C++98, no FFmpeg run: DOCKER_BUILDKIT=1 docker build -f trunk/Dockerfile.builds --target centos7-ansi-no-ffmpeg . + outputs: + SRS_BUILD_CENTOS7_DONE: ok build-centos6: name: build-centos6 @@ -37,6 +67,8 @@ jobs: run: DOCKER_BUILDKIT=1 docker build -f trunk/Dockerfile.builds --target centos6-baseline . - name: Build on CentOS6, with all features run: DOCKER_BUILDKIT=1 docker build -f trunk/Dockerfile.builds --target centos6-all . + outputs: + SRS_BUILD_CENTOS6_DONE: ok build-ubuntu16: name: build-ubuntu16 @@ -51,6 +83,8 @@ jobs: run: DOCKER_BUILDKIT=1 docker build -f trunk/Dockerfile.builds --target ubuntu16-baseline . - name: Build on Ubuntu16, with all features run: DOCKER_BUILDKIT=1 docker build -f trunk/Dockerfile.builds --target ubuntu16-all . + outputs: + SRS_BUILD_UBUNTU16_DONE: ok build-ubuntu18: name: build-ubuntu18 @@ -65,6 +99,8 @@ jobs: run: DOCKER_BUILDKIT=1 docker build -f trunk/Dockerfile.builds --target ubuntu18-baseline . - name: Build on Ubuntu18, with all features run: DOCKER_BUILDKIT=1 docker build -f trunk/Dockerfile.builds --target ubuntu18-all . + outputs: + SRS_BUILD_UBUNTU18_DONE: ok build-ubuntu20: name: build-ubuntu20 @@ -79,6 +115,8 @@ jobs: run: DOCKER_BUILDKIT=1 docker build -f trunk/Dockerfile.builds --target ubuntu20-baseline . - name: Build on Ubuntu20, with all features run: DOCKER_BUILDKIT=1 docker build -f trunk/Dockerfile.builds --target ubuntu20-all . + outputs: + SRS_BUILD_UBUNTU20_DONE: ok build-cross-arm: name: build-cross-arm @@ -92,6 +130,8 @@ jobs: run: DOCKER_BUILDKIT=1 docker build -f trunk/Dockerfile.builds --target ubuntu16-cross-armv7 . - name: Cross Build for ARMv7 on Ubuntu20 run: DOCKER_BUILDKIT=1 docker build -f trunk/Dockerfile.builds --target ubuntu20-cross-armv7 . + outputs: + SRS_BUILD_CROSS_ARM_DONE: ok build-cross-aarch64: name: build-cross-aarch64 @@ -105,6 +145,8 @@ jobs: run: DOCKER_BUILDKIT=1 docker build -f trunk/Dockerfile.builds --target ubuntu16-cross-aarch64 . - name: Cross Build for AARCH64 on Ubuntu20 run: DOCKER_BUILDKIT=1 docker build -f trunk/Dockerfile.builds --target ubuntu20-cross-aarch64 . + outputs: + SRS_BUILD_CROSS_AARCH64_DONE: ok build: name: build @@ -119,6 +161,8 @@ jobs: runs-on: ubuntu-20.04 steps: - run: echo 'Build done' + outputs: + SRS_BUILD_DONE: ok utest: name: utest @@ -135,10 +179,14 @@ jobs: # For regression-test - name: Run SRS regression-test run: docker run --rm srs:test bash -c 'make && (./objs/srs -c conf/regression-test.conf; ./etc/init.d/srs status) && cd 3rdparty/srs-bench && make && ./objs/srs_test -test.v' + outputs: + SRS_UTEST_DONE: ok coverage: name: coverage runs-on: ubuntu-20.04 + needs: + - utest steps: - name: Checkout repository uses: actions/checkout@v2 @@ -166,6 +214,8 @@ jobs: --env SRS_BRANCH=$SRS_BRANCH --env SRS_PR=$SRS_PR --env SRS_SHA=$SRS_SHA --env SRS_PROJECT=$SRS_PROJECT \ srs:cov bash -c 'make utest && ./objs/srs_utest && bash auto/codecov.sh' # + outputs: + SRS_COVERAGE_DONE: ok multile-arch-armv7: name: multile-arch-armv7 @@ -186,6 +236,8 @@ jobs: --output "type=image,push=false" \ --build-arg IMAGE=ossrs/srs:ubuntu20-cache \ -f trunk/Dockerfile . + outputs: + SRS_MULTIPLE_ARCH_ARMV7_DONE: ok multile-arch-aarch64: name: multile-arch-aarch64 @@ -206,10 +258,14 @@ jobs: --output "type=image,push=false" \ --build-arg IMAGE=ossrs/srs:ubuntu20-cache \ -f trunk/Dockerfile . + outputs: + SRS_MULTIPLE_ARCH_AARCH64_DONE: ok multile-arch-amd64: name: multile-arch-amd64 runs-on: ubuntu-20.04 + needs: + - utest steps: - name: Checkout repository uses: actions/checkout@v2 @@ -226,10 +282,13 @@ jobs: --output "type=image,push=false" \ --build-arg IMAGE=ossrs/srs:ubuntu20-cache \ -f trunk/Dockerfile . + outputs: + SRS_MULTIPLE_ARCH_AMD64_DONE: ok done: name: done needs: + - cygwin64 - build - coverage - multile-arch-armv7 diff --git a/.gitignore b/.gitignore index 066cff572..63880f228 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ .idea .DS_Store *.heap +*.exe cmake-build-debug /trunk/ide/srs_clion/CMakeCache.txt diff --git a/trunk/3rdparty/patches/srtp/cygwin-crypto-include-config.h b/trunk/3rdparty/patches/srtp/cygwin-crypto-include-config.h new file mode 100644 index 000000000..c7764b3d0 --- /dev/null +++ b/trunk/3rdparty/patches/srtp/cygwin-crypto-include-config.h @@ -0,0 +1,194 @@ +/* crypto/include/config.h. Generated from config_in.h by configure. */ +/* config_in.h. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define if building for a CISC machine (e.g. Intel). */ +#define CPU_CISC 1 + +/* Define if building for a RISC machine (assume slow byte access). */ +/* #undef CPU_RISC */ + +/* Define to enabled debug logging for all mudules. */ +/* #undef ENABLE_DEBUG_LOGGING */ + +/* Logging statments will be writen to this file. */ +/* #undef ERR_REPORTING_FILE */ + +/* Define to redirect logging to stdout. */ +/* #undef ERR_REPORTING_STDOUT */ + +/* Define this to use AES-GCM. */ +/* #undef GCM */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_BYTESWAP_H 1 + +/* Define to 1 if you have the `inet_aton' function. */ +#define HAVE_INET_ATON 1 + +/* Define to 1 if the system has the type `int16_t'. */ +#define HAVE_INT16_T 1 + +/* Define to 1 if the system has the type `int32_t'. */ +#define HAVE_INT32_T 1 + +/* Define to 1 if the system has the type `int8_t'. */ +#define HAVE_INT8_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `dl' library (-ldl). */ +/* #undef HAVE_LIBDL */ + +/* Define to 1 if you have the `nspr4' library (-lnspr4). */ +/* #undef HAVE_LIBNSPR4 */ + +/* Define to 1 if you have the `nss3' library (-lnss3). */ +/* #undef HAVE_LIBNSS3 */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define to 1 if you have the `z' library (-lz). */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MACHINE_TYPES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NSS_H */ + +/* Define to 1 if you have the `winpcap' library (-lwpcap) */ +/* #undef HAVE_PCAP */ + +/* Define to 1 if you have the `sigaction' function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_INT_TYPES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define to 1 if the system has the type `uint16_t'. */ +#define HAVE_UINT16_T 1 + +/* Define to 1 if the system has the type `uint32_t'. */ +#define HAVE_UINT32_T 1 + +/* Define to 1 if the system has the type `uint64_t'. */ +#define HAVE_UINT64_T 1 + +/* Define to 1 if the system has the type `uint8_t'. */ +#define HAVE_UINT8_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `usleep' function. */ +#define HAVE_USLEEP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_WINDOWS_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to use X86 inlined assembly code */ +#define HAVE_X86 1 + +/* Define this to use NSS crypto. */ +/* #undef NSS */ + +/* Define this to use OpenSSL crypto. */ +/* #undef OPENSSL */ + +/* Define this to use OpenSSL KDF for SRTP. */ +/* #undef OPENSSL_KDF */ + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "https://github.com/cisco/libsrtp/issues" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libsrtp2" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libsrtp2 2.3.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libsrtp2" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "2.3.0" + +/* The size of `unsigned long', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_LONG 8 + +/* The size of `unsigned long long', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_LONG_LONG 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ diff --git a/trunk/3rdparty/patches/srtp/cygwin-gcm-crypto-include-config.h b/trunk/3rdparty/patches/srtp/cygwin-gcm-crypto-include-config.h new file mode 100644 index 000000000..916b6ba79 --- /dev/null +++ b/trunk/3rdparty/patches/srtp/cygwin-gcm-crypto-include-config.h @@ -0,0 +1,194 @@ +/* crypto/include/config.h. Generated from config_in.h by configure. */ +/* config_in.h. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define if building for a CISC machine (e.g. Intel). */ +#define CPU_CISC 1 + +/* Define if building for a RISC machine (assume slow byte access). */ +/* #undef CPU_RISC */ + +/* Define to enabled debug logging for all mudules. */ +/* #undef ENABLE_DEBUG_LOGGING */ + +/* Logging statments will be writen to this file. */ +/* #undef ERR_REPORTING_FILE */ + +/* Define to redirect logging to stdout. */ +/* #undef ERR_REPORTING_STDOUT */ + +/* Define this to use AES-GCM. */ +#define GCM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_BYTESWAP_H 1 + +/* Define to 1 if you have the `inet_aton' function. */ +#define HAVE_INET_ATON 1 + +/* Define to 1 if the system has the type `int16_t'. */ +#define HAVE_INT16_T 1 + +/* Define to 1 if the system has the type `int32_t'. */ +#define HAVE_INT32_T 1 + +/* Define to 1 if the system has the type `int8_t'. */ +#define HAVE_INT8_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `dl' library (-ldl). */ +/* #undef HAVE_LIBDL */ + +/* Define to 1 if you have the `nspr4' library (-lnspr4). */ +/* #undef HAVE_LIBNSPR4 */ + +/* Define to 1 if you have the `nss3' library (-lnss3). */ +/* #undef HAVE_LIBNSS3 */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define to 1 if you have the `z' library (-lz). */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MACHINE_TYPES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NSS_H */ + +/* Define to 1 if you have the `winpcap' library (-lwpcap) */ +/* #undef HAVE_PCAP */ + +/* Define to 1 if you have the `sigaction' function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_INT_TYPES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define to 1 if the system has the type `uint16_t'. */ +#define HAVE_UINT16_T 1 + +/* Define to 1 if the system has the type `uint32_t'. */ +#define HAVE_UINT32_T 1 + +/* Define to 1 if the system has the type `uint64_t'. */ +#define HAVE_UINT64_T 1 + +/* Define to 1 if the system has the type `uint8_t'. */ +#define HAVE_UINT8_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `usleep' function. */ +#define HAVE_USLEEP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_WINDOWS_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to use X86 inlined assembly code */ +#define HAVE_X86 1 + +/* Define this to use NSS crypto. */ +/* #undef NSS */ + +/* Define this to use OpenSSL crypto. */ +#define OPENSSL 1 + +/* Define this to use OpenSSL KDF for SRTP. */ +/* #undef OPENSSL_KDF */ + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "https://github.com/cisco/libsrtp/issues" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libsrtp2" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libsrtp2 2.3.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libsrtp2" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "2.3.0" + +/* The size of `unsigned long', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_LONG 8 + +/* The size of `unsigned long long', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_LONG_LONG 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ diff --git a/trunk/auto/depends.sh b/trunk/auto/depends.sh index 8f886a7ad..763b0254e 100755 --- a/trunk/auto/depends.sh +++ b/trunk/auto/depends.sh @@ -616,6 +616,15 @@ if [[ $SRS_RTC == YES ]]; then cd ${SRS_OBJS}/${SRS_PLATFORM}/libsrtp-2-fit && $SRTP_CONFIGURE ${SRTP_OPTIONS} --prefix=${SRS_DEPENDS_LIBS}/${SRS_PLATFORM}/3rdpatry/srtp2 ) && + # Sometimes it might fail because autoconf failed to generate crypto/include.config.h + if [[ $SRS_CYGWIN64 == YES ]]; then + SRS_PATCH_SOURCE=${SRS_WORKDIR}/3rdparty/patches/srtp/cygwin-crypto-include-config.h + if [[ $SRS_SRTP_ASM == YES ]]; then + SRS_PATCH_SOURCE=${SRS_WORKDIR}/3rdparty/patches/srtp/cygwin-gcm-crypto-include-config.h + fi + grep -q 'HAVE_UINT64_T 1' ${SRS_OBJS}/${SRS_PLATFORM}/libsrtp-2-fit/crypto/include/config.h || + cp -f $SRS_PATCH_SOURCE ${SRS_OBJS}/${SRS_PLATFORM}/libsrtp-2-fit/crypto/include/config.h + fi && make -C ${SRS_OBJS}/${SRS_PLATFORM}/libsrtp-2-fit ${SRS_JOBS} && make -C ${SRS_OBJS}/${SRS_PLATFORM}/libsrtp-2-fit install && cp -rf ${SRS_OBJS}/${SRS_PLATFORM}/3rdpatry/srtp2 ${SRS_OBJS}/ && diff --git a/trunk/auto/options.sh b/trunk/auto/options.sh index acd8464bf..acdb240e5 100755 --- a/trunk/auto/options.sh +++ b/trunk/auto/options.sh @@ -528,12 +528,6 @@ function apply_auto_options() { echo "Force single thread for cygwin64" SRS_SINGLE_THREAD=YES fi - # TODO: FIXME: Cygwin: Build srtp with openssl fail for no srtp_aes_icm_ctx_t - # See https://github.com/ossrs/srs/issues/3254 - if [[ $SRS_CYGWIN64 == YES && $SRS_SRTP_ASM == YES ]]; then - echo "Disable SRTP with openssl for cygwin64" - SRS_SRTP_ASM=NO - fi # parse the jobs for make if [[ ! -z SRS_JOBS ]]; then diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index 83e2f4318..85b189f20 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -8,6 +8,7 @@ The changelog for SRS. ## SRS 5.0 Changelog +* v5.0, 2022-11-20, For [#2532](https://github.com/ossrs/srs/issues/2532): Windows: Support cygwin pipline and packager. v5.0.89 * v5.0, 2022-11-18, Fix [#3215](https://github.com/ossrs/srs/issues/3215): Callback: Fix bug for response string 0. v5.0.88 * v5.0, 2022-11-18, For [#2532](https://github.com/ossrs/srs/issues/2532): Windows: Replace ln by cp for windows. v5.0.87 * v5.0, 2022-10-31, For [#2899](https://github.com/ossrs/srs/issues/2899): Exporter: Add metrics cpu, memory and uname. v5.0.86 diff --git a/trunk/doc/Features.md b/trunk/doc/Features.md index 2e2468cad..a6ce1421f 100644 --- a/trunk/doc/Features.md +++ b/trunk/doc/Features.md @@ -23,6 +23,7 @@ The features of SRS. - [x] System: [Experimental] Support distributed tracing by Tencent Cloud APM. v5.0.64+ - [x] System: [Experimental] Support grab backtrace stack when assert fail. v5.0.80+ - [x] System: [Experimental] Support Google Address Sanitizer, [#3216](https://github.com/ossrs/srs/issues/3216). v5.0.81+ +- [x] System: [Experimental] Windows: Support cygwin pipline and packager, [#2532](https://github.com/ossrs/srs/issues/2532). v5.0.89+ - [x] API: Support HTTP API([CN](https://ossrs.net/lts/zh-cn/docs/v4/doc/http-api), [EN](https://ossrs.io/lts/en-us/docs/v4/doc/http-api)) for system management. - [x] API: Support HTTP callback([CN](https://ossrs.net/lts/zh-cn/docs/v4/doc/http-callback), [EN](https://ossrs.io/lts/en-us/docs/v4/doc/http-callback)) for authentication and integration. - [x] API: Support reuse HTTP Stream port for HTTP API, [#2881](https://github.com/ossrs/srs/issues/2881). diff --git a/trunk/doc/srs-logo.ico b/trunk/doc/srs-logo.ico new file mode 100644 index 0000000000000000000000000000000000000000..d45b92ef8200a04b55ea484b3cd17cd044bba859 GIT binary patch literal 44798 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 KLB)Oh@c#owi^aMC literal 0 HcmV?d00001 diff --git a/trunk/packaging/nsis/srs-cli.bat b/trunk/packaging/nsis/srs-cli.bat new file mode 100644 index 000000000..7d2a59b38 --- /dev/null +++ b/trunk/packaging/nsis/srs-cli.bat @@ -0,0 +1,11 @@ +for /f "tokens=2*" %%i in ('REG QUERY "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\App Paths\srs\ins_dir"') do set srs_home=%%j + +echo %srs_home% + +for %%I in ("%srs_home%") do set srs_disk=%%~dI + +cd %srs_home% +@%srs_disk% + +objs\srs.exe -c conf\console.conf +cmd \ No newline at end of file diff --git a/trunk/packaging/nsis/srs-live.bat b/trunk/packaging/nsis/srs-live.bat new file mode 100644 index 000000000..f4f2e0e34 --- /dev/null +++ b/trunk/packaging/nsis/srs-live.bat @@ -0,0 +1,11 @@ +for /f "tokens=2*" %%i in ('REG QUERY "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\App Paths\srs\ins_dir"') do set srs_home=%%j + +echo %srs_home% + +for %%I in ("%srs_home%") do set srs_disk=%%~dI + +cd %srs_home% +@%srs_disk% + +objs\srs.exe -c conf\live.conf +cmd diff --git a/trunk/packaging/nsis/srs-rtc.bat b/trunk/packaging/nsis/srs-rtc.bat new file mode 100644 index 000000000..478b32f38 --- /dev/null +++ b/trunk/packaging/nsis/srs-rtc.bat @@ -0,0 +1,11 @@ +for /f "tokens=2*" %%i in ('REG QUERY "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\App Paths\srs\ins_dir"') do set srs_home=%%j + +echo %srs_home% + +for %%I in ("%srs_home%") do set srs_disk=%%~dI + +cd %srs_home% +@%srs_disk% + +objs\srs.exe -c conf\rtc.conf +cmd diff --git a/trunk/packaging/nsis/srs.nsi b/trunk/packaging/nsis/srs.nsi new file mode 100644 index 000000000..681ab017f --- /dev/null +++ b/trunk/packaging/nsis/srs.nsi @@ -0,0 +1,154 @@ +; Script generated by the HM NIS Edit Script Wizard. +; See https://nsis.sourceforge.io/Download +; "C:\Program Files (x86)\NSIS\makensis.exe" /DSRS_VERSION=5.0.89 /DCYGWIN_DIR="C:\tools\cygwin" srs.nsi +; "/cygdrive/c/Program Files (x86)/NSIS/makensis.exe" /DSRS_VERSION=5.0.89 /DCYGWIN_DIR="C:\cygwin64" srs.nsi +; "/cygdrive/c/Program Files (x86)/NSIS/makensis.exe" /DSRS_VERSION=$(../../objs/srs -v 2>&1) /DCYGWIN_DIR="C:\cygwin64" srs.nsi +; "/cygdrive/c/Program Files (x86)/NSIS/makensis.exe" /DSRS_VERSION=$(./objs/srs -v 2>&1) /DCYGWIN_DIR="C:\cygwin64" packaging/nsis/srs.nsi + +; HM NIS Edit Wizard helper defines +!define PRODUCT_NAME "SRS" +!define PRODUCT_VERSION "${SRS_VERSION}" +!define PRODUCT_PUBLISHER "ossrs" +!define PRODUCT_WEB_SITE "https://ossrs.io" +!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\srs.exe" +!define PRODUCT_INSTALL_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\srs\ins_dir" +!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" +!define PRODUCT_UNINST_ROOT_KEY "HKLM" + +; MUI 1.67 compatible ------ +!include "MUI.nsh" + +; MUI Settings +!define MUI_ABORTWARNING +!define MUI_ICON "..\..\doc\srs-logo.ico" +!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico" + +; Welcome page +!insertmacro MUI_PAGE_WELCOME +; License page +!insertmacro MUI_PAGE_LICENSE "..\..\..\LICENSE" +; Directory page +!insertmacro MUI_PAGE_DIRECTORY +; Instfiles page +!insertmacro MUI_PAGE_INSTFILES +; Finish page +;!define MUI_FINISHPAGE_RUN "$INSTDIR\srs-cli.bat" +!insertmacro MUI_PAGE_FINISH + +; Uninstaller pages +!insertmacro MUI_UNPAGE_INSTFILES + +; Language files +!insertmacro MUI_LANGUAGE "English" + +; MUI end ------ + +Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" +OutFile "SRS-Windows-x86_64-${PRODUCT_VERSION}-setup.exe" +InstallDir "$PROGRAMFILES\SRS" +InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" "" +ShowInstDetails show +ShowUnInstDetails show + +Section "MainSection" SEC01 + SetOutPath "$INSTDIR" + SetOverwrite ifnewer + File "..\..\..\LICENSE" + File ".\*.bat" + SetOutPath "$INSTDIR\conf" + SetOverwrite try + File "..\..\conf\*.conf" + SetOutPath "$INSTDIR\logo" + File "..\..\doc\srs-logo.ico" + SetOutPath "$INSTDIR\objs" + File "${CYGWIN_DIR}\bin\cyggcc_s-seh-1.dll" + File "${CYGWIN_DIR}\bin\cygstdc++-6.dll" + File "${CYGWIN_DIR}\bin\cygwin1.dll" + SetOutPath "$INSTDIR\objs\nginx\html" + File "..\..\objs\nginx\html\nginx.html" + File "..\..\objs\nginx\html\favicon.ico" + File "..\..\objs\nginx\html\index.html" + SetOutPath "$INSTDIR\objs\nginx\html\live" + File "..\..\objs\nginx\html\live\livestream.html" + SetOutPath "$INSTDIR\objs\nginx\html\console" + File /r "..\..\objs\nginx\html\console\" + SetOutPath "$INSTDIR\objs\nginx\html\demos" + File /r "..\..\objs\nginx\html\demos\" + SetOutPath "$INSTDIR\objs\nginx\html\players" + File /r "..\..\objs\nginx\html\players\" + SetOutPath "$INSTDIR\objs" + File "..\..\objs\srs.exe" + File ".\srs.pid" + SetOutPath "$INSTDIR" + CreateDirectory "$SMPROGRAMS\SRS" + CreateShortCut "$SMPROGRAMS\SRS\SRS.lnk" "$INSTDIR\srs-cli.bat" "" "$INSTDIR\logo\srs-logo.ico" + CreateShortCut "$DESKTOP\SRS.lnk" "$INSTDIR\srs-cli.bat" "" "$INSTDIR\logo\srs-logo.ico" +SectionEnd + +Section -AdditionalIcons + SetOutPath $INSTDIR + CreateShortCut "$SMPROGRAMS\SRS\Uninstall.lnk" "$INSTDIR\uninst.exe" +SectionEnd + +Section -Post + WriteUninstaller "$INSTDIR\uninst.exe" + WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\objs\srs.exe" + WriteRegStr HKLM "${PRODUCT_INSTALL_REGKEY}" "" "$INSTDIR" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\objs\srs.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}" +SectionEnd + + +Function un.onUninstSuccess + HideWindow + MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) is removed from your computer." +FunctionEnd + +Function un.onInit + MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Uninstall $(^Name) from your computer?" IDYES +2 + Abort +FunctionEnd + +Section Uninstall + Delete "$INSTDIR\uninst.exe" + Delete "$INSTDIR\objs\srs.pid" + Delete "$INSTDIR\objs\srs.exe" + Delete "$INSTDIR\objs\nginx\html\nginx.html" + Delete "$INSTDIR\objs\nginx\html\live\livestream.html" + Delete "$INSTDIR\objs\nginx\html\index.html" + Delete "$INSTDIR\objs\nginx\html\favicon.ico" + Delete "$INSTDIR\objs\cygwin1.dll" + Delete "$INSTDIR\objs\cygstdc++-6.dll" + Delete "$INSTDIR\objs\cyggcc_s-seh-1.dll" + Delete "$INSTDIR\logo\srs-logo.ico" + Delete "$INSTDIR\conf\*.conf" + Delete "$INSTDIR\LICENSE" + Delete "$INSTDIR\srs-cli.bat" + Delete "$INSTDIR\srs-live.bat" + Delete "$INSTDIR\srs-rtc.bat" + + Delete "$SMPROGRAMS\SRS\Uninstall.lnk" + Delete "$DESKTOP\SRS.lnk" + Delete "$SMPROGRAMS\SRS\SRS.lnk" + + RMDir "$SMPROGRAMS\SRS" + RMDir /r "$INSTDIR\objs\nginx\html\players" + RMDir /r "$INSTDIR\objs\nginx\html\demos" + RMDir /r "$INSTDIR\objs\nginx\html\console" + RMDir "$INSTDIR\objs\nginx\html\live" + RMDir "$INSTDIR\objs\nginx\html" + RMDir "$INSTDIR\objs\nginx" + RMDir "$INSTDIR\objs" + RMDir "$INSTDIR\logo" + RMDir "$INSTDIR\conf" + RMDir "$INSTDIR" + + DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" + DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}" + DeleteRegKey HKLM "${PRODUCT_INSTALL_REGKEY}" + SetAutoClose true +SectionEnd \ No newline at end of file diff --git a/trunk/packaging/nsis/srs.pid b/trunk/packaging/nsis/srs.pid new file mode 100644 index 000000000..e69de29bb diff --git a/trunk/src/core/srs_core_version5.hpp b/trunk/src/core/srs_core_version5.hpp index 578e57b69..2ac588ea4 100644 --- a/trunk/src/core/srs_core_version5.hpp +++ b/trunk/src/core/srs_core_version5.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 5 #define VERSION_MINOR 0 -#define VERSION_REVISION 88 +#define VERSION_REVISION 89 #endif