diff --git a/.github/workflows/build-test-run-reusable-workflow.yaml b/.github/workflows/build-test-run-reusable-workflow.yaml index 7e2cdac5..61d1aba0 100644 --- a/.github/workflows/build-test-run-reusable-workflow.yaml +++ b/.github/workflows/build-test-run-reusable-workflow.yaml @@ -30,6 +30,7 @@ jobs: with: python-version: '3.11' - run: | + python -u Scripts/ConanSetup.py python -u Scripts/BuildAndInstallExternalLibs.py --TargetPlatform ${{ inputs.target-platform }} python -u Scripts/BuildAndInstallCoDeLib.py --TargetPlatform ${{ inputs.target-platform }} python -u Scripts/BuildBenchmark.py --TargetPlatform ${{ inputs.target-platform }} diff --git a/.gitignore b/.gitignore index d0670fc6..983e9656 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,11 @@ Test*.txt* # Python __pycache__/ +.venv # Custom AddedFlags.cmake -tmp \ No newline at end of file +tmp + +# Conan +build/ diff --git a/Benchmark/CMakeLists.txt b/Benchmark/CMakeLists.txt index 237679e9..a570a3b9 100644 --- a/Benchmark/CMakeLists.txt +++ b/Benchmark/CMakeLists.txt @@ -3,6 +3,10 @@ include(FetchContent) project(COMPRESSION_DECOMPRESSION_BENCHMARK C) +list(APPEND CMAKE_PREFIX_PATH ${MINIZIP_INSTALL_PATH}) +list(APPEND CMAKE_PREFIX_PATH ${CODELIB_INSTALL_PATH}) +message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}") + # b63 FetchContent_Declare( b63 diff --git a/CoDeLib/CMakeLists.txt b/CoDeLib/CMakeLists.txt index aa5607e3..0d7d47bc 100644 --- a/CoDeLib/CMakeLists.txt +++ b/CoDeLib/CMakeLists.txt @@ -1,6 +1,9 @@ cmake_minimum_required(VERSION 3.28) project(COMPRESSION_DECOMPRESSION_LIB VERSION 0.0.1 LANGUAGES C) +list(APPEND CMAKE_PREFIX_PATH ${MINIZIP_INSTALL_PATH}) +message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}") + add_compile_definitions("$<$>:NDEBUG>") # Required for FileUtils.c (and its tests) to use the correct versions of ftello and similar functions diff --git a/ConanProfiles/Linux_x86_64 b/ConanProfiles/Linux_x86_64 new file mode 100644 index 00000000..980d712e --- /dev/null +++ b/ConanProfiles/Linux_x86_64 @@ -0,0 +1,10 @@ +[settings] +arch=x86_64 +compiler=gcc +compiler.libcxx=libstdc++11 +compiler.version=14 +os=Linux + +# https://github.com/conan-io/conan-center-index/issues/19340 +[conf] +tools.build:compiler_executables={ "c" : "gcc", "cpp": "g++" } \ No newline at end of file diff --git a/ConanProfiles/Windows_x86_64 b/ConanProfiles/Windows_x86_64 new file mode 100644 index 00000000..7874fe32 --- /dev/null +++ b/ConanProfiles/Windows_x86_64 @@ -0,0 +1,10 @@ +[settings] +arch=x86_64 +compiler=gcc +compiler.libcxx=libstdc++11 +compiler.version=14 +os=Windows + +# https://github.com/conan-io/conan-center-index/issues/19340 +[conf] +tools.build:compiler_executables={ "c" : "gcc", "cpp": "g++" } \ No newline at end of file diff --git a/DevEnvSetup.md b/DevEnvSetup.md index c66a2cff..32d7bbcf 100644 --- a/DevEnvSetup.md +++ b/DevEnvSetup.md @@ -32,6 +32,13 @@ Install the recommended packages for this reposity (see `./vscode/extensions.jso - Install **C development packages**: `$ apt install build-essential` - Install **CMake**: https://cmake.org/download/ (>= 3.28) +# Conan + +```sh +$ python ./Scripts/ConanSetup.py +``` + + # Verify Now you should be able build and run: diff --git a/Scripts/BuildAndInstallCoDeLib.py b/Scripts/BuildAndInstallCoDeLib.py index c7551998..01aca194 100644 --- a/Scripts/BuildAndInstallCoDeLib.py +++ b/Scripts/BuildAndInstallCoDeLib.py @@ -46,9 +46,6 @@ def BuildAndInstallCoDeLib( buildEnv.GetTargetPlatform() ) - ExternalZlibLibInstallPath = Path( - ExternalLibPath / "zlib/Install" / targetPlatformString / BuildTypeString - ) ExternalMinizipNgLibInstallPath = Path( ExternalLibPath / "minizip-ng/Install" / targetPlatformString / BuildTypeString ) @@ -73,14 +70,19 @@ def BuildAndInstallCoDeLib( print("==============================") print(ProjectName + ": Configuring ({})".format(BuildTypeString)) print("==============================") - configureCommand = 'cmake -G "{0}" -DCMAKE_TOOLCHAIN_FILE="{1}" -S "{2}" -B "{3}" -DCMAKE_INSTALL_PREFIX="{4}" -DCMAKE_BUILD_TYPE={5} -DZLIB_ROOT="{6}" -DCMAKE_PREFIX_PATH="{7}"'.format( + configureCommand = 'cmake -G "{0}" -DCMAKE_TOOLCHAIN_FILE="{1}" -S "{2}" -B "{3}" -DCMAKE_INSTALL_PREFIX="{4}" -DCMAKE_BUILD_TYPE={5} -DMINIZIP_INSTALL_PATH="{6}"'.format( buildEnv.GetCmakeGenerator(), - buildEnv.GetCustomToolChainPath(), + Path( + RepositoryRootPath + / "build/conan/build" + / BuildTypeString + / "generators" + / "conan_toolchain.cmake" + ), CoDeLibRootPath, BuildDirectory, InstallDirectory, BuildTypeString, - ExternalZlibLibInstallPath, ExternalMinizipNgLibInstallPath, ) print(configureCommand) @@ -93,7 +95,9 @@ def BuildAndInstallCoDeLib( print("==============================") print(ProjectName + ": Building ({})".format(BuildTypeString)) print("==============================") - buildCommand = "cmake --build {0} -- -j 4".format(BuildDirectory) + buildCommand = "cmake --build {0} --config {1} -- -j 4".format( + BuildDirectory, BuildTypeString + ) print(buildCommand) subprocess.run( buildCommand, diff --git a/Scripts/BuildAndInstallExternalLibs.py b/Scripts/BuildAndInstallExternalLibs.py index 021ba629..8fc9abbf 100644 --- a/Scripts/BuildAndInstallExternalLibs.py +++ b/Scripts/BuildAndInstallExternalLibs.py @@ -36,82 +36,6 @@ ExternalLibPath = Path(RepositoryRootPath / "External") -############################## -# zlib -############################## -def BuildAndInstallZlib( - buildEnv: EnvironmentConfig.EnvironmentConfiguration, - buildConfig: EnvironmentConfig.BuildConfig = EnvironmentConfig.BuildConfig.DEBUG, -): - ProjectName = "zlib" - - BuildTypeString = EnvironmentConfig.BuildConfig.ToCMakeBuildType(buildConfig) - targetPlatformString = EnvironmentConfig.Platform.PlatformToOsName( - buildEnv.GetTargetPlatform() - ) - - TopLevelCMakeListsDirectory = Path(ExternalLibPath / ProjectName) - BuildDirectory = Path( - ExternalLibPath / ProjectName / "Build" / targetPlatformString / BuildTypeString - ) - InstallDirectory = Path( - ExternalLibPath - / ProjectName - / "Install" - / targetPlatformString - / BuildTypeString - ) - - if not BuildDirectory.exists(): - BuildDirectory.mkdir(parents=True) - - if InstallDirectory.exists(): - shutil.rmtree(InstallDirectory) - InstallDirectory.mkdir(parents=True) - - os.chdir(RepositoryRootPath) - - print("==============================") - print(ProjectName + ": Configuring ({})".format(BuildTypeString)) - print("==============================") - configureCommand = 'cmake -G "{0}" -DCMAKE_TOOLCHAIN_FILE="{1}" -S {2} -B {3} -DCMAKE_INSTALL_PREFIX="{4}" -DZLIB_BUILD_EXAMPLES=OFF -DCMAKE_BUILD_TYPE={5} -DZLIB_BUILD_SHARED=OFF'.format( - buildEnv.GetCmakeGenerator(), - buildEnv.GetCustomToolChainPath(), - TopLevelCMakeListsDirectory, - BuildDirectory, - InstallDirectory, - BuildTypeString, - ) - print(configureCommand) - subprocess.run( - configureCommand, - shell=True, - check=True, - ) - - print("==============================") - print(ProjectName + ": Building ({})".format(BuildTypeString)) - print("==============================") - buildCommand = "cmake --build {0} -- -j 4".format(BuildDirectory) - print(buildCommand) - subprocess.run( - buildCommand, - shell=True, - check=True, - ) - - print("==============================") - print(ProjectName + ": Installing ({})".format(BuildTypeString)) - print("==============================") - installCommand = "cmake --install {0}".format(BuildDirectory) - print(installCommand) - subprocess.run( - installCommand, - shell=True, - check=True, - ) - - ############################## # minizip-ng ############################## @@ -170,7 +94,9 @@ def BuildAndInstallMinizipNg( print("==============================") print(ProjectName + ": Building ({})".format(BuildTypeString)) print("==============================") - buildCommand = "cmake --build {0}".format(BuildDirectory) + buildCommand = "cmake --build {0} --config {1} -- -j 4".format( + BuildDirectory, BuildTypeString + ) print(buildCommand) subprocess.run( buildCommand, @@ -194,10 +120,6 @@ def BuildAndInstallMinizipNg( RepositoryRootPath, targetPlatform ) -# zlib -BuildAndInstallZlib(BuildEnv, EnvironmentConfig.BuildConfig.DEBUG) -BuildAndInstallZlib(BuildEnv, EnvironmentConfig.BuildConfig.RELEASE) - # minizip-ng BuildAndInstallMinizipNg(BuildEnv, EnvironmentConfig.BuildConfig.DEBUG) BuildAndInstallMinizipNg(BuildEnv, EnvironmentConfig.BuildConfig.RELEASE) diff --git a/Scripts/BuildBenchmark.py b/Scripts/BuildBenchmark.py index df44e152..ad9e16b1 100644 --- a/Scripts/BuildBenchmark.py +++ b/Scripts/BuildBenchmark.py @@ -52,9 +52,7 @@ def BuildBenchmark( CoDeLibInstallDirectory = Path( CoDeLibPath / "Install" / targetPlatformString / BuildTypeString ) - ExternalZlibLibInstallPath = Path( - ExternalLibPath / "zlib/Install" / targetPlatformString / BuildTypeString - ) + ExternalMinizipNgLibInstallPath = Path( ExternalLibPath / "minizip-ng/Install" / targetPlatformString / BuildTypeString ) @@ -72,16 +70,22 @@ def BuildBenchmark( print("==============================") print(ProjectName + ": Configuring ({})".format(BuildTypeString)) print("==============================") - configureCommand = 'cmake -G "{0}" -DCMAKE_TOOLCHAIN_FILE="{1}" -S {2} -B {3} -DCMAKE_BUILD_TYPE={4} -DZLIB_ROOT="{5}" -DCMAKE_PREFIX_PATH="{6};{7}"'.format( + configureCommand = 'cmake -G "{0}" -DCMAKE_TOOLCHAIN_FILE="{1}" -S {2} -B {3} -DCMAKE_BUILD_TYPE={4} -DMINIZIP_INSTALL_PATH="{5}" -DCODELIB_INSTALL_PATH="{6}"'.format( buildEnv.GetCmakeGenerator(), - buildEnv.GetCustomToolChainPath(), + Path( + RepositoryRootPath + / "build/conan/build" + / BuildTypeString + / "generators" + / "conan_toolchain.cmake" + ), BenchmarkRootPath, BuildDirectory, BuildTypeString, - ExternalZlibLibInstallPath, - CoDeLibInstallDirectory, ExternalMinizipNgLibInstallPath, + CoDeLibInstallDirectory, ) + print(configureCommand) subprocess.run( configureCommand, shell=True, @@ -91,7 +95,10 @@ def BuildBenchmark( print("==============================") print(ProjectName + ": Building ({})".format(BuildTypeString)) print("==============================") - buildCommand = "cmake --build {0} -- -j 4".format(BuildDirectory) + buildCommand = "cmake --build {0} --config {1} -- -j 4".format( + BuildDirectory, BuildTypeString + ) + print(buildCommand) subprocess.run( buildCommand, shell=True, diff --git a/Scripts/ConanSetup.py b/Scripts/ConanSetup.py new file mode 100644 index 00000000..123a58f3 --- /dev/null +++ b/Scripts/ConanSetup.py @@ -0,0 +1,107 @@ +import os +from pathlib import Path +import EnvironmentConfig +import subprocess + +hostPlatform = EnvironmentConfig.Platform.OsNameToPlatform(os.name) + +currentScriptPath = Path(os.path.dirname(os.path.abspath(__file__))) +repositoryRootPath = Path(currentScriptPath.parent) + +venvPath = Path(repositoryRootPath / ".venv") +if not venvPath.exists(): + print("Creating virtual environment at {}".format(venvPath)) + subprocess.run( + "python -m venv {}".format(venvPath), + shell=True, + check=True, + ) +else: + print("Virtual environment already exists at {}".format(venvPath)) + +print("Activating virtual environment...") + +VirtualEnvPythonPath = Path( + venvPath + / ("Scripts" if hostPlatform == EnvironmentConfig.Platform.WINDOWS else "bin") + / "python" +) + + +print("Upgrading pip...") +pipUpgradeCommand = "{} -m pip install --upgrade pip".format(VirtualEnvPythonPath) +print(pipUpgradeCommand) +subprocess.run( + pipUpgradeCommand, + shell=True, + check=True, +) + +requirementsFilePath = Path(repositoryRootPath / "requirements.txt") +if requirementsFilePath.exists(): + print("Installing required packages from {}".format(requirementsFilePath)) + installCommand = "{} -m pip install -r {}".format( + VirtualEnvPythonPath, requirementsFilePath + ) + print(installCommand) + subprocess.run( + installCommand, + shell=True, + check=True, + ) +else: + print( + "No requirements.txt file found at {}, skipping package installation.".format( + requirementsFilePath + ) + ) + +print("Virtual environment setup complete.") + +VirtualEnvConanPath = Path( + venvPath + / ("Scripts" if hostPlatform == EnvironmentConfig.Platform.WINDOWS else "bin") + / "conan" +) + +print("Getting conan profile...") +conanProfileCommand = "{} profile detect --force".format(VirtualEnvConanPath) +print(conanProfileCommand) +subprocess.run( + conanProfileCommand, + shell=True, + check=True, +) + +print("Getting Conan dependencies...") +buildTypes = ["Debug", "Release"] +profiles = ["Windows_x86_64", "Linux_x86_64"] +for profile in profiles: + if ( + hostPlatform == EnvironmentConfig.Platform.WINDOWS + and profile.startswith("Linux") + ) or ( + hostPlatform == EnvironmentConfig.Platform.LINUX + and profile.startswith("Windows") + ): + continue + for buildType in buildTypes: + print( + "Installing Conan dependencies for build type '{}' and profile '{}'...".format( + buildType, profile + ) + ) + conanInstallCommand = '{0} install "{1}" --profile:host={2} --profile:build={3} --output-folder="{4}" --build=missing --settings=build_type={5}'.format( + VirtualEnvConanPath, + Path(repositoryRootPath / "conanfile.py"), + Path(repositoryRootPath / "ConanProfiles" / profile), + Path(repositoryRootPath / "ConanProfiles" / profile), + Path(repositoryRootPath / "build" / "conan"), + buildType, + ) + print(conanInstallCommand) + subprocess.run( + conanInstallCommand, + shell=True, + check=True, + ) diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 00000000..8b2f17ef --- /dev/null +++ b/conanfile.py @@ -0,0 +1,16 @@ +from conan import ConanFile +from conan.tools.cmake import cmake_layout + + +class ExampleRecipe(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "CMakeDeps", "CMakeToolchain" + + def requirements(self): + self.requires("zlib/1.3.1") + + def configure(self): + self.options["zlib/*"].shared = False + + def layout(self): + cmake_layout(self) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..09b71273 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +conan==2.21.0 \ No newline at end of file