예제 #1
0
 def test_cmake_toolchain__without_toolchain(self):
     config = BuildConfig()
     cmake_toolchain1 = config.get("cmake_toolchain", None)
     cmake_toolchain2 = config["cmake_toolchain"]
     assert config.cmake_toolchain is None
     assert cmake_toolchain1 is None
     assert cmake_toolchain2 is None
예제 #2
0
 def test_cmake_generator__without_generator(self):
     config = BuildConfig()
     cmake_generator1 = config.get("cmake_generator", None)
     cmake_generator2 = config["cmake_generator"]
     assert config.cmake_generator is None
     assert cmake_generator1 is None
     assert cmake_generator2 is None
예제 #3
0
 def test_cmake_defines_add__with_existing_item_removes_it(self):
     definitions = [("one", "VALUE_1"), ("two", "VALUE_2")]
     config = BuildConfig(cmake_defines=definitions)
     config.cmake_defines_remove("two")
     expected = [("one", "VALUE_1"), ("CMAKE_BUILD_TYPE", None)]
     assert list(config.cmake_defines.items()) == expected
     assert list(config["cmake_defines"].items()) == expected
예제 #4
0
 def test_cmake_defines__set(self):
     config = BuildConfig()
     definitions = [("one", "VALUE_1"), ("two", "VALUE_2")]
     config.cmake_defines = definitions  # XXX-BAD
     # XXX expected = [("CMAKE_BUILD_TYPE", None)] + definitions
     assert list(config.cmake_defines.items()) == definitions
     assert list(config["cmake_defines"].items()) == definitions
예제 #5
0
 def test_cmake_defines__with_one_item(self):
     config = BuildConfig(cmake_defines=[("one", "VALUE_1")])
     expected = [("one", "VALUE_1"), ("CMAKE_BUILD_TYPE", None)]
     assert isinstance(config.cmake_defines, OrderedDict)
     assert list(config.cmake_defines.items()) == expected
     assert list(config.get("cmake_defines").items()) == expected
     assert list(config["cmake_defines"].items()) == expected
     assert list(config.data.get("cmake_defines").items()) == expected
예제 #6
0
    def test_derive_cmake_build_type_and_assign(self, build_config_name,
                                                expected):
        config = BuildConfig(build_config_name, cmake_build_type="INITIAL")
        assert config.name == build_config_name
        assert config.cmake_build_type == "INITIAL"

        cmake_build_type = config.derive_cmake_build_type_and_assign()
        assert cmake_build_type == expected
        assert config.cmake_build_type == expected
예제 #7
0
    def test_derive_cmake_build_type_if_unconfigured(self, build_config_name,
                                                     expected):
        config = BuildConfig(build_config_name)
        config.cmake_build_type = None  # -- DISABLED: default-init.
        assert config.name == build_config_name
        assert config.cmake_build_type is None, "ENSURE: No assignment"

        cmake_build_type = config.derive_cmake_build_type_if_unconfigured()
        assert cmake_build_type == expected
        assert config.cmake_build_type == expected
예제 #8
0
 def test_cmake_defines_add__with_new_item_appends(self):
     config = BuildConfig(cmake_defines=[("one", "VALUE_1")])
     config.cmake_defines_add("NEW", "NEW_VALUE")
     expected = [
         ("one", "VALUE_1"),
         ("CMAKE_BUILD_TYPE", None),
         ("NEW", "NEW_VALUE"),
     ]
     assert list(config.cmake_defines.items()) == expected
     assert list(config["cmake_defines"].items()) == expected
예제 #9
0
    def test_derive_cmake_build_type_if_unconfigured__with_initial_value(
            self, build_config_name, expected):
        config = BuildConfig(build_config_name, cmake_build_type="INITIAL")
        assert config.name == build_config_name
        assert config.cmake_build_type == "INITIAL"

        config.derive_cmake_build_type_if_unconfigured()
        derived_build_type = config.derive_cmake_build_type()
        assert config.cmake_build_type == "INITIAL", "ENSURE: INITIAL value is preserved."
        assert derived_build_type == expected
        assert derived_build_type != "INITIAL"
예제 #10
0
    def test_build__auto_init_with_nonexisting_build_dir(self, tmpdir, capsys):
        ctx = MockContext()
        project_dir = Path(str(tmpdir))
        project_build_dir = project_dir/"build"
        build_config = BuildConfig(cmake_generator="ninja")
        cmake_project1 = CMakeProject(ctx, project_dir, project_build_dir, build_config)
        assert not project_build_dir.isdir()

        # -- STEP: First cmake_project.build => AUTO CMAKE-INIT: project_build_dir
        with cd(project_dir):
            assert not project_build_dir.exists()
            cmake_project1.build()

            # -- POSTCONDITIONS:
            expected_commands = [
                "cmake -G Ninja ..",
                "cmake --build .",
            ]
            assert ctx.commands == expected_commands
            cmake_build_filename = project_build_dir / CMakeProjectPersistConfig.FILE_BASENAME
            captured = capsys.readouterr()
            assert_cmake_project_used_init_using_captured(cmake_project1, captured,
                                                          cmake_generator="ninja")
            # assert "CMAKE-INIT:  build (using cmake.generator=ninja)" in captured.out
            assert "CMAKE-BUILD: build" in captured.out
            assert project_build_dir.exists()
            assert cmake_build_filename.exists()
예제 #11
0
    def test_init__skip_same_data(self, tmpdir, capsys):
        ctx = MockContext()
        project_dir = Path(str(tmpdir))
        project_build_dir = project_dir/"build"
        build_config = BuildConfig(cmake_generator="NINJA")
        cmake_project1 = CMakeProject(ctx, project_dir, project_build_dir, build_config)
        assert not project_build_dir.isdir()

        # -- STEP 1: First cmake_project.init
        with cd(project_dir):
            cmake_project1.init()

            # -- POSTCONDITIONS:
            cmake_build_filename = project_build_dir / CMakeProjectPersistConfig.FILE_BASENAME
            assert project_build_dir.exists(), "ENSURE: project_build_dir exists"
            assert cmake_build_filename.exists()
            captured = capsys.readouterr()
            assert_cmake_project_used_init_using_captured(cmake_project1, captured,
                                                          cmake_generator="NINJA")

        # -- STEP 2: Second cmake_project.init => SKIPPED
        with cd(project_dir):
            ctx.clear()
            cmake_project2 = CMakeProject(ctx, project_dir.relpath(),
                                          project_build_dir.relpath(),
                                          build_config)
            cmake_project2.init()
            captured = capsys.readouterr()
            assert ctx.last_command is None
            assert_cmake_project_skipped_reinit_using_captured(cmake_project1, captured)
예제 #12
0
    def test_init__when_build_dir_exists_with_other_persistent_schema(self, tmpdir, capsys):
        ctx = MockContext()
        project_dir = Path(str(tmpdir))
        project_build_dir = project_dir/"build"
        build_config = BuildConfig(cmake_generator="ninja", cmake_build_type="debug")
        assert not project_build_dir.isdir()

        # -- STEP 1: First cmake_project.init
        with cd(project_dir):
            cmake_project1 = CMakeProject(ctx, project_dir, project_build_dir, build_config)
            cmake_project1.init()
            cmake_build_filename = project_build_dir / CMakeProjectPersistConfig.FILE_BASENAME
            assert project_build_dir.exists(), "ENSURE: project_build_dir exists"
            assert cmake_build_filename.exists()

            # -- STEP: Fake cmake-build init with other persistent data schema.
            # HINT: May occur when cmake-build is updated, but project_build_dir still exists.
            with open(cmake_build_filename, "w") as f:
                f.write("""{ "other": 123, "cmake_generator": "ninja" }""")

        # -- STEP 2: Second try to cmake_project.init()
        # ENSURE: No failure / AssertionError occurs
        with cd(project_dir):
            cmake_project2 = CMakeProject(ctx, project_dir, project_build_dir, build_config)
            assert cmake_project2.initialized
            assert not cmake_project2.needs_reinit()
            assert cmake_project2.needs_update()
            cmake_project2.init()

            assert not cmake_project2.needs_reinit()
            assert not cmake_project2.needs_update()
            captured = capsys.readouterr()
            assert_cmake_project_needed_update_using_captured(cmake_project2, captured,
                                                            cmake_generator="ninja")
예제 #13
0
    def test_init__init_without_build_dir(self, tmpdir):
        ctx = MockContext()
        project_dir = Path(str(tmpdir))
        project_build_dir = project_dir/"build"
        build_config = BuildConfig(cmake_generator="NINJA")
        cmake_project = CMakeProject(ctx, project_dir, project_build_dir, build_config)
        assert not project_build_dir.isdir()

        with cd(project_dir):
            cmake_project.init()
            assert ctx.last_command == "cmake -G NINJA .."
예제 #14
0
    def test_build__performs_reinit_with_existing_build_dir_and_other_cmake_generator(self, tmpdir, capsys):
        ctx = MockContext()
        project_dir = Path(str(tmpdir))
        project_build_dir = project_dir/"build"
        build_config = BuildConfig(cmake_generator="ninja")
        assert not project_build_dir.isdir()

        # -- STEP 1: First cmake_project.init
        with cd(project_dir):
            cmake_project1 = CMakeProject(ctx, project_dir, project_build_dir, build_config)
            cmake_project1.init()

            # -- POSTCONDITIONS:
            cmake_build_filename = project_build_dir / CMakeProjectPersistConfig.FILE_BASENAME
            assert project_build_dir.exists(), "ENSURE: project_build_dir exists"
            assert cmake_build_filename.exists()
            captured = capsys.readouterr()
            assert_cmake_project_used_init_using_captured(cmake_project1, captured,
                                                          cmake_generator="ninja")
            # assert "CMAKE-INIT:  build (using cmake.generator=ninja)" in captured.out
            assert ctx.last_command == "cmake -G Ninja .."

        # -- STEP 2: Second cmake_project.build => REINIT.
        ctx.clear()
        with cd(project_dir):
            build_config.cmake_generator = "OTHER"   # ONLY-DEFAULT
            cmake_project2 = CMakeProject(ctx, project_dir, project_build_dir, build_config,
                                          cmake_generator="make")
            assert cmake_project2.needs_reinit()
            cmake_project2.build()

            # -- POSTCONDITIONS:
            expected_commands = [
                'cmake -G "Unix Makefiles" ..',
                "cmake --build ."
            ]
            assert ctx.commands == expected_commands
            captured = capsys.readouterr()
            assert_cmake_project_used_reinit_using_captured(cmake_project2, captured,
                                                            cmake_generator="make")
예제 #15
0
    def test_init__skips_reinit_with_existing_build_dir_and_generator_none(self, tmpdir, capsys):
        ctx = MockContext()
        project_dir = Path(str(tmpdir))
        project_build_dir = project_dir/"build"
        build_config = BuildConfig(cmake_generator="ninja")
        assert not project_build_dir.isdir()

        # -- STEP 1: First cmake_project.init
        with cd(project_dir):
            cmake_project1 = CMakeProject(ctx, project_dir, project_build_dir, build_config)
            cmake_project1.init()

            # -- POSTCONDITIONS:
            cmake_build_filename = project_build_dir / CMakeProjectPersistConfig.FILE_BASENAME
            assert project_build_dir.exists(), "ENSURE: project_build_dir exists"
            assert cmake_build_filename.exists()
            captured = capsys.readouterr()
            assert_cmake_project_used_init_using_captured(cmake_project1, captured,
                                                          cmake_generator="ninja")
            # assert "CMAKE-INIT:  build (using cmake.generator=ninja)" in captured.out
            assert ctx.last_command == "cmake -G Ninja .."

        # -- STEP 2: Second cmake_project.build => SKIP-REINIT.
        # REASON:
        #   * Inherit stored.cmake_generator (if it is not overridden).
        #   * Keep stored.cmake_generator until explicit reinit.
        ctx.clear()
        with cd(project_dir):
            build_config.cmake_generator = "OTHER"  # -- ONLY DEFAULT-VALUE
            cmake_project2 = CMakeProject(ctx, project_dir, project_build_dir, build_config,
                                          cmake_generator=None)
            assert not cmake_project2.needs_reinit()
            cmake_project2.init()

            # -- POSTCONDITIONS:
            expected_commands = []
            assert ctx.commands == expected_commands
            captured = capsys.readouterr()
            assert_cmake_project_skipped_reinit_using_captured(cmake_project2, captured,
                                                               cmake_generator="ninja")
예제 #16
0
    def make_newborn(tmpdir, cmake_generator=None, cmake_build_type=None):
        """Create NEW-BORN CMake project without build-directory."""
        cmake_generator = cmake_generator or DEFAULT_CMAKE_GENERATOR
        cmake_build_type = cmake_build_type or DEFAULT_CMAKE_BUILD_TYPE
        ctx = MockContext()
        project_dir = Path(str(tmpdir))
        project_build_dir = project_dir / "build"
        build_config = BuildConfig(cmake_generator=cmake_generator,
                                   cmake_build_type=cmake_build_type)
        assert not project_build_dir.isdir()

        # -- STEP 1: First cmake_project.init
        with cd(project_dir):
            cmake_project = CMakeProject(ctx, project_dir, project_build_dir,
                                         build_config)
            return cmake_project
예제 #17
0
    def __init__(self,
                 ctx,
                 project_dir=None,
                 project_build_dir=None,
                 build_config=None,
                 cmake_generator=None):
        if build_config is None:
            cmake_build_type = self.CMAKE_BUILD_TYPE_DEFAULT
            build_config = BuildConfig("default",
                                       cmake_build_type=cmake_build_type)

        project_dir = Path(project_dir or ".")
        project_dir = project_dir.abspath()
        if not project_build_dir:
            build_dir = make_build_dir_from_schema(ctx.config,
                                                   build_config.name)
            project_build_dir = project_dir / build_dir

        config_name = build_config.name
        cmake_generator_default = build_config.cmake_generator
        cmake_toolchain = build_config.cmake_toolchain

        self.ctx = ctx
        self.project_dir = project_dir
        self.project_build_dir = Path(project_build_dir).abspath()
        self.config = None
        self._build_config = build_config
        self._stored_config = None
        self._stored_cmake_generator = None
        self._dirty = True
        self._placeholder_map = {}
        self.load_config()
        self.update_from_initial_config(build_config)
        self.config.name = config_name
        if not cmake_generator:
            # -- INHERIT: Stored cmake_generator, if it is not overridden.
            cmake_generator = self._stored_config.cmake_generator or \
                              cmake_generator_default
        self.config.cmake_generator = cmake_generator
        self.config.cmake_toolchain = cmake_toolchain
        self.cmake_install_prefix = self.replace_placeholders(
            self.cmake_install_prefix)
        self.cmake_config_overrides_cmake_build_type = \
            self.CMAKE_CONFIG_OVERRIDES_CMAKE_BUILD_TYPE
        # MAYBE:
        # self.cmake_defines = self.replace_placeholders(self.cmake_defines)
        self._dirty = True
예제 #18
0
def make_build_config(ctx, name=None):
    if name == "host_debug" or name == "auto":
        name = HOST_BUILD_CONFIG_DEBUG
    elif name == "host_release":
        name = HOST_BUILD_CONFIG_RELEASE

    name = name or ctx.config.build_config or "default"
    build_config_defaults = make_build_config_defaults(ctx.config)
    build_config_data = {}
    build_config_data.update(build_config_defaults)
    build_config_data2 = ctx.config.build_configs_map.get(name) or {}
    build_config_data.update(build_config_data2)

    # -- STEP: Make cmake_toolchain path relative to config_dir.
    config_dir = ctx.config.config_dir or "."
    cmake_toolchain = build_config_data.get("cmake_toolchain")
    if cmake_toolchain:
        # -- ASSUMPTION: cmake_toolchain is a relative-path.
        cmake_toolchain = Path(cmake_toolchain)
        if not cmake_toolchain.isabs():
            cmake_toolchain = Path(config_dir) / cmake_toolchain
            cmake_toolchain = cmake_toolchain.normpath()
            build_config_data["cmake_toolchain"] = cmake_toolchain

    # -- STEP: build_config.cmake_defines inherits common.cmake_defines
    cmake_defines = build_config_defaults["cmake_defines"]
    cmake_defines_items = cmake_defines_normalize(
        build_config_data2.get("cmake_defines", []))
    if cmake_defines_items:
        # -- INHERIT DEFAULT CMAKE_DEFINES (override and/or merge them):
        use_override = cmake_defines_items[0][0] == "@override"
        if use_override:
            cmake_defines = OrderedDict(cmake_defines_items)
        else:
            # -- MERGE-AND-OVERRIDE:
            # New items are added, existing items replaced/overwritten.
            cmake_defines = cmake_defines.copy()
            cmake_defines.update(OrderedDict(cmake_defines_items))

    build_config_data["cmake_defines"] = cmake_defines
    return BuildConfig(name, build_config_data)
예제 #19
0
    def test_init__performs_reinit_with_other_cmake_generator(self, tmpdir, capsys):
        ctx = MockContext()
        project_dir = Path(str(tmpdir)).abspath()
        project_build_dir = project_dir/"build"
        build_config = BuildConfig(cmake_generator="make")
        cmake_project1 = CMakeProject(ctx, project_dir, project_build_dir, build_config)
        assert not project_build_dir.isdir()

        # -- STEP 1: First cmake_project.init
        with cd(project_dir):
            cmake_project1.init()

            # -- POSTCONDITIONS:
            cmake_build_filename = project_build_dir / CMakeProjectPersistConfig.FILE_BASENAME
            assert project_build_dir.exists(), "ENSURE: project_build_dir exists"
            assert cmake_build_filename.exists()
            captured = capsys.readouterr()
            assert_cmake_project_used_init_using_captured(cmake_project1, captured,
                                                          cmake_generator="make")
            # assert "CMAKE-INIT:  build (using cmake.generator=make)" in captured.out
            assert ctx.last_command == 'cmake -G "Unix Makefiles" ..'

        # -- STEP 2: Second cmake_project.init => REINIT: Other cmake_generator is used.
        with cd(project_dir):
            ctx.clear()
            # build_config.cmake_generator = "ninja"
            cmake_project2 = CMakeProject(ctx, project_dir.relpath(),
                                          project_build_dir.relpath(), build_config,
                                          cmake_generator="ninja")
            assert cmake_project2.needs_reinit(), "ENSURE: Need for reinit"
            cmake_project2.init()
            captured = capsys.readouterr()
            assert_cmake_project_used_reinit_using_captured(cmake_project2, captured,
                                                          cmake_generator="ninja")
            # assert "CMAKE-INIT:  build (NEEDS-REINIT)" in captured.out
            # assert "CMAKE-INIT:  build (using cmake.generator=ninja)" in captured.out
            assert ctx.last_command == "cmake -G Ninja .."
예제 #20
0
 def test_cmake_toolchain__with_toolchain(self):
     config = BuildConfig(cmake_toolchain="cmake/toolchain_1.cmake")
     assert config.cmake_toolchain == "cmake/toolchain_1.cmake"
     assert config.get("cmake_toolchain") == "cmake/toolchain_1.cmake"
     assert config["cmake_toolchain"] == "cmake/toolchain_1.cmake"
예제 #21
0
 def test_cmake_generator__with_generator(self):
     config = BuildConfig(cmake_generator="foo")
     assert config.cmake_generator == "foo"
     assert config.get("cmake_generator") == "foo"
     assert config["cmake_generator"] == "foo"
     assert config.data.get("cmake_generator") == "foo"
예제 #22
0
 def test_derive_cmake_build_type__returns_none_without_name(self):
     config = BuildConfig()
     cmake_build_type = config.derive_cmake_build_type()
     assert config.name == "default"
     assert cmake_build_type is None
예제 #23
0
 def test_derive_cmake_build_type(self, build_config_name, expected):
     config = BuildConfig(build_config_name)
     cmake_build_type = config.derive_cmake_build_type()
     assert config.name == build_config_name
     assert cmake_build_type == expected
예제 #24
0
 def test_cmake_defines__without_explicit_init(self):
     config = BuildConfig("debug")
     expected = [("CMAKE_BUILD_TYPE", "Debug")]
     assert list(config.cmake_defines.items()) == expected
     assert list(config["cmake_defines"].items()) == expected
예제 #25
0
 def test_cmake_defines_remove__with_unknown_item(self):
     config = BuildConfig(cmake_defines=[("one", "VALUE_1")])
     config.cmake_defines_remove("UNKNOWN")
     expected = [("one", "VALUE_1"), ("CMAKE_BUILD_TYPE", None)]
     assert list(config.cmake_defines.items()) == expected
     assert list(config["cmake_defines"].items()) == expected