Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cc65: migrate to Conan v2 #18873

Merged
merged 10 commits into from
Jan 2, 2024
4 changes: 0 additions & 4 deletions recipes/cc65/all/conandata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,9 @@
url: "https://github.com/cc65/cc65/archive/V2.19.tar.gz"
sha256: "157b8051aed7f534e5093471e734e7a95e509c577324099c3c81324ed9d0de77"
patches:
"2.18":
- patch_file: "patches/2.18-0001-no-embedded-paths-makefile.patch"

Check warning on line 10 in recipes/cc65/all/conandata.yml

View workflow job for this annotation

GitHub Actions / Lint changed files (YAML files)

conandata.yml schema warning

Schema outlined in https://github.com/conan-io/conan-center-index/blob/master/docs/adding_packages/conandata_yml_format.md#patches-fields is not followed. required key(s) 'patch_description', 'patch_type' not found in - patch_file: patches/2.18-000 ... ^ (line: 10)
base_path: "source_subfolder"
- patch_file: "patches/2.18-0002-libsrc-use-extension.patch"

Check warning on line 11 in recipes/cc65/all/conandata.yml

View workflow job for this annotation

GitHub Actions / Lint changed files (YAML files)

conandata.yml schema warning

Schema outlined in https://github.com/conan-io/conan-center-index/blob/master/docs/adding_packages/conandata_yml_format.md#patches-fields is not followed. required key(s) 'patch_description', 'patch_type' not found in - patch_file: patches/2.18-000 ... ^ (line: 11)
base_path: "source_subfolder"
"2.19":
- patch_file: "patches/2.19-0001-no-embedded-paths-makefile.patch"

Check warning on line 13 in recipes/cc65/all/conandata.yml

View workflow job for this annotation

GitHub Actions / Lint changed files (YAML files)

conandata.yml schema warning

Schema outlined in https://github.com/conan-io/conan-center-index/blob/master/docs/adding_packages/conandata_yml_format.md#patches-fields is not followed. required key(s) 'patch_description', 'patch_type' not found in - patch_file: patches/2.19-000 ... ^ (line: 13)
base_path: "source_subfolder"
- patch_file: "patches/2.19-0002-libsrc-use-extension.patch"

Check warning on line 14 in recipes/cc65/all/conandata.yml

View workflow job for this annotation

GitHub Actions / Lint changed files (YAML files)

conandata.yml schema warning

Schema outlined in https://github.com/conan-io/conan-center-index/blob/master/docs/adding_packages/conandata_yml_format.md#patches-fields is not followed. required key(s) 'patch_description', 'patch_type' not found in - patch_file: patches/2.19-000 ... ^ (line: 14)
base_path: "source_subfolder"
241 changes: 114 additions & 127 deletions recipes/cc65/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,163 +1,150 @@
from conans import AutoToolsBuildEnvironment, ConanFile, MSBuild, tools
from conans.errors import ConanInvalidConfiguration
import os

from conan import ConanFile
from conan.errors import ConanInvalidConfiguration
from conan.tools.build import can_run
from conan.tools.files import apply_conandata_patches, chdir, copy, export_conandata_patches, get, replace_in_file, rmdir
from conan.tools.gnu import Autotools, AutotoolsToolchain
from conan.tools.layout import basic_layout
from conan.tools.microsoft import MSBuild, is_msvc, msvs_toolset, MSBuildToolchain

required_conan_version = ">=1.53.0"


class Cc65Conan(ConanFile):
name = "cc65"
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://cc65.github.io/"
description = "A freeware C compiler for 6502 based systems"
license = "Zlib"
topics = ("conan", "cc65", "compiler", "cmos", "6502", "8bit")
exports_sources = "patches/**"
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://cc65.github.io/"
topics = ("compiler", "cmos", "6502", "8bit")

package_type = "application"
settings = "os", "arch", "compiler", "build_type"

_autotools = None
_source_subfolder = "source_subfolder"
def export_sources(self):
export_conandata_patches(self)

def configure(self):
del self.settings.compiler.libcxx
del self.settings.compiler.cppstd
if self.settings.compiler == "Visual Studio":
if self.settings.arch not in ("x86", "x86_64"):
raise ConanInvalidConfiguration("Invalid arch")
self.settings.rm_safe("compiler.libcxx")
self.settings.rm_safe("compiler.cppstd")

def layout(self):
basic_layout(self, src_folder="src")

def package_id(self):
if is_msvc(self.info):
if self.info.settings.arch == "x86_64":
self.info.settings.arch = "x86"
del self.info.settings.compiler

def validate(self):
if not can_run(self):
raise ConanInvalidConfiguration(
f"Compiling for {self.settings.arch} is not supported. "
"cc65 needs to be able to run the built executables during the build process"
)
if is_msvc(self):
if self.settings.arch not in ["x86", "x86_64"]:
raise ConanInvalidConfiguration(f"{self.settings.arch} is not supported on MSVC")
if self.settings.arch == "x86_64":
self.output.info("This recipe will build x86 instead of x86_64 (the binaries are compatible)")

def build_requirements(self):
if self.settings.compiler == "Visual Studio" and not tools.which("make"):
self.build_requires("make/4.2.1")
if is_msvc(self):
self.tool_requires("make/4.4")

def source(self):
tools.get(**self.conan_data["sources"][self.version])
extracted_dir = self.name + "-" + self.version
os.rename(extracted_dir, self._source_subfolder)

@property
def _datadir(self):
return os.path.join(self.package_folder, "bin", "share", "cc65")

@property
def _samplesdir(self):
return os.path.join(self.package_folder, "samples")

def _build_msvc(self):
msbuild = MSBuild(self)
msvc_platforms = {
"x86": "Win32",
}
arch = str(self.settings.arch)
if arch != "x86":
self.output.warn("{} detected: building x86 instead".format(self.settings.arch))
arch = "x86"

msbuild.build(os.path.join(self._source_subfolder, "src", "cc65.sln"),
build_type="Debug" if self.settings.build_type == "Debug" else "Release",
arch=arch, platforms=msvc_platforms)
autotools = self._configure_autotools()
with tools.chdir(os.path.join(self._source_subfolder, "libsrc")):
autotools.make()

def _configure_autotools(self):
if self._autotools:
return self._autotools
self._autotools = AutoToolsBuildEnvironment(self)
return self._autotools

@property
def _make_args(self):
datadir = self._datadir
prefix = self.package_folder
samplesdir = self._samplesdir
if tools.os_info.is_windows:
datadir = tools.unix_path(datadir)
prefix = tools.unix_path(prefix)
samplesdir = tools.unix_path(samplesdir)
args = [
"PREFIX={}".format(prefix),
"datadir={}".format(datadir),
"samplesdir={}".format(samplesdir),
get(self, **self.conan_data["sources"][self.version], strip_root=True)

def generate(self):
if is_msvc(self):
tc = MSBuildToolchain(self)
tc.generate()
tc = AutotoolsToolchain(self)
tc.make_args += [
f"PREFIX=/",

Check warning on line 66 in recipes/cc65/all/conanfile.py

View workflow job for this annotation

GitHub Actions / Lint changed conanfile.py (v2 migration)

Using an f-string that does not have any interpolated variables
f"datadir=/bin/share/cc65",

Check warning on line 67 in recipes/cc65/all/conanfile.py

View workflow job for this annotation

GitHub Actions / Lint changed conanfile.py (v2 migration)

Using an f-string that does not have any interpolated variables
f"samplesdir=/samples",

Check warning on line 68 in recipes/cc65/all/conanfile.py

View workflow job for this annotation

GitHub Actions / Lint changed conanfile.py (v2 migration)

Using an f-string that does not have any interpolated variables
danimtb marked this conversation as resolved.
Show resolved Hide resolved
]
if self.settings.os == "Windows":
args.append("EXE_SUFFIX=.exe")
return args

def _build_autotools(self):
autotools = self._configure_autotools()
with tools.chdir(os.path.join(self._source_subfolder)):
autotools.make(args=self._make_args)
tc.make_args.append("EXE_SUFFIX=.exe")
tc.generate()

def _patch_sources(self):
for patch in self.conan_data["patches"][self.version]:
tools.patch(**patch)
if self.settings.compiler == "Visual Studio":
with tools.chdir(os.path.join(self._source_subfolder, "src")):
for fn in os.listdir("."):
if not fn.endswith(".vcxproj"):
continue
tools.replace_in_file(fn, "v141", tools.msvs_toolset(self))
tools.replace_in_file(fn, "<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>", "")
apply_conandata_patches(self)
if is_msvc(self):
for vcxproj in self.source_path.joinpath("src").rglob("*.vcxproj"):
replace_in_file(self, vcxproj, "v141", msvs_toolset(self))
replace_in_file(self, vcxproj, "<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>", "")
if self.settings.os == "Windows":
# Add ".exe" suffix to calls from cl65 to other utilities
for fn, var in (("cc65", "CC65"), ("ca65", "CA65"), ("co65", "CO65"), ("ld65", "LD65"), ("grc65", "GRC")):
v = "{},".format(var).ljust(5)
tools.replace_in_file(os.path.join(self._source_subfolder, "src", "cl65", "main.c"),
"CmdInit (&{v} CmdPath, \"{n}\");".format(v=v, n=fn),
"CmdInit (&{v} CmdPath, \"{n}.exe\");".format(v=v, n=fn))
for fn, var in [
("cc65", "CC65"),
("ca65", "CA65"),
("co65", "CO65"),
("ld65", "LD65"),
("grc65", "GRC"),
]:
v = f"{var},".ljust(5)
replace_in_file(self, os.path.join(self.source_folder, "src", "cl65", "main.c"),
f'CmdInit (&{v} CmdPath, "{fn}");',
f'CmdInit (&{v} CmdPath, "{fn}.exe");')
# Fix mkdir failing on Windows due to -p being unavailable there
# https://github.com/conan-io/conan-center-index/pull/18873#issuecomment-1841989876
replace_in_file(self, os.path.join(self.source_folder, "libsrc", "Makefile"),
r'MKDIR = mkdir $(subst /,\,$1)',
r'MKDIR = if not exist "$(subst /,\,$1)" mkdir "$(subst /,\,$1)"')

def build(self):
self._patch_sources()
if self.settings.compiler == "Visual Studio":
self._build_msvc()
if is_msvc(self):
msbuild = MSBuild(self)
msbuild.platform = "Win32"
msbuild.build_type = "Debug" if self.settings.build_type == "Debug" else "Release"
msbuild.build(sln=os.path.join(self.source_folder, "src", "cc65.sln"))
with chdir(self, os.path.join(self.source_folder, "libsrc")):
autotools = Autotools(self)
autotools.make()
else:
self._build_autotools()

def _package_msvc(self):
self.copy("*.exe", src=os.path.join(self._source_subfolder, "bin"), dst=os.path.join(self.package_folder, "bin"), keep_path=False)
for dir in ("asminc", "cfg", "include", "lib", "target"):
self.copy("*", src=os.path.join(self._source_subfolder, dir), dst=os.path.join(self._datadir, dir))

def _package_autotools(self):
autotools = self._configure_autotools()
with tools.chdir(os.path.join(self.build_folder, self._source_subfolder)):
autotools.install(args=self._make_args)

tools.rmdir(self._samplesdir)
tools.rmdir(os.path.join(self.package_folder, "share"))
with chdir(self, self.source_folder):
autotools = Autotools(self)
autotools.make()

def package(self):
self.copy(pattern="LICENSE", dst="licenses", src=self._source_subfolder)
if self.settings.compiler == "Visual Studio":
self._package_msvc()
copy(self, "LICENSE", self.source_folder, os.path.join(self.package_folder, "licenses"))
if is_msvc(self):
copy(self, "*.exe",
dst=os.path.join(self.package_folder, "bin"),
src=os.path.join(self.source_folder, "bin"),
keep_path=False)
for dir in ("asminc", "cfg", "include", "lib", "target"):

Check warning on line 121 in recipes/cc65/all/conanfile.py

View workflow job for this annotation

GitHub Actions / Lint changed conanfile.py (v2 migration)

Redefining built-in 'dir'
copy(self, "*",
dst=os.path.join(self.package_folder, "bin", "share", "cc65", dir),
src=os.path.join(self.source_folder, dir))
danimtb marked this conversation as resolved.
Show resolved Hide resolved
else:
self._package_autotools()

def package_id(self):
del self.info.settings.compiler
if self.settings.compiler == "Visual Studio":
if self.settings.arch == "x86_64":
self.info.settings.arch = "x86"
with chdir(self, os.path.join(self.source_folder)):
autotools = Autotools(self)
autotools.install()
rmdir(self, os.path.join(self.package_path, "samples"))
rmdir(self, os.path.join(self.package_folder, "share"))

def package_info(self):
bindir = os.path.join(self.package_folder, "bin")
self.output.info("Appending PATH environment variable: %s" % bindir)
self.env_info.PATH.append(bindir)

self.output.info("Seting CC65_HOME environment variable: %s" % self._datadir)
self.env_info.CC65_HOME = self._datadir
self.cpp_info.frameworkdirs = []
self.cpp_info.libdirs = []
self.cpp_info.resdirs = []
self.cpp_info.includedirs = []

bin_ext = ".exe" if self.settings.os == "Windows" else ""
bindir = os.path.join(self.package_folder, "bin")
self.buildenv_info.define_path("CC65_HOME", os.path.join(self.package_folder, "bin", "share", "cc65"))
self.buildenv_info.define_path("CC65", os.path.join(bindir, "cc65" + bin_ext))
self.buildenv_info.define_path("AS65", os.path.join(bindir, "ca65" + bin_ext))
self.buildenv_info.define_path("LD65", os.path.join(bindir, "cl65" + bin_ext))

cc65_cc = os.path.join(bindir, "cc65" + bin_ext)
self.output.info("Seting CC65 environment variable: {}".format(cc65_cc))
self.env_info.CC65 = cc65_cc

cc65_as = os.path.join(bindir, "ca65" + bin_ext)
self.output.info("Seting AS65 environment variable: {}".format(cc65_as))
self.env_info.AS65 = cc65_as

cc65_ld = os.path.join(bindir, "cl65" + bin_ext)
self.output.info("Seting LD65 environment variable: {}".format(cc65_ld))
self.env_info.LD65 = cc65_ld
# TODO: Legacy, to be removed on Conan 2.0
self.env_info.PATH.append(bindir)
self.env_info.CC65_HOME = os.path.join(self.package_folder, "bin", "share", "cc65")
self.env_info.CC65 = os.path.join(bindir, "cc65" + bin_ext)
self.env_info.AS65 = os.path.join(bindir, "ca65" + bin_ext)
self.env_info.LD65 = os.path.join(bindir, "cl65" + bin_ext)
42 changes: 24 additions & 18 deletions recipes/cc65/all/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,39 @@
from conans import ConanFile, tools
import os
import shutil

from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.files import mkdir, rm
from conan.tools.layout import basic_layout


class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"

exports_sources = "hello.c", "text.s"
generators = "VirtualRunEnv", "VirtualBuildEnv"
test_type = "explicit"

_targets = ("c64", "apple2")

def build_requirements(self):
self.tool_requires(self.tested_reference_str)

def layout(self):
basic_layout(self)

def build(self):
if not tools.cross_building(self.settings):
for src in self.exports_sources:
if can_run(self):
for src in ["hello.c", "text.s"]:
shutil.copy(os.path.join(self.source_folder, src), os.path.join(self.build_folder, src))
for target in self._targets:
output = "hello_{}".format(target)
tools.mkdir(target)
try:
# Try removing the output file to give confidence it is created by cc65
os.unlink(output)
except FileNotFoundError:
pass
self.run("{p} -O -t {t} hello.c -o {t}/hello.s".format(p=os.environ["CC65"], t=target))
self.run("{p} -t {t} {t}/hello.s -o {t}/hello.o".format(p=os.environ["AS65"], t=target))
self.run("{p} -t {t} text.s -o {t}/text.o".format(p=os.environ["AS65"], t=target))
self.run("{p} -o {o} -t {t} {t}/hello.o {t}/text.o {t}.lib".format(o=output, p=os.environ["LD65"], t=target))
output = f"hello_{target}"
mkdir(self, target)
rm(self, output, self.build_folder)
self.run(f"cc65 -O -t {target} hello.c -o {target}/hello.s")
self.run(f"ca65 -t {target} {target}/hello.s -o {target}/hello.o")
self.run(f"ca65 -t {target} text.s -o {target}/text.o")
self.run(f"ld65 -o {output} -t {target} {target}/hello.o {target}/text.o {target}.lib")

def test(self):
if not tools.cross_building(self.settings):
if can_run(self):
for target in self._targets:
assert os.path.isfile("hello_{}".format(target))
assert os.path.isfile(f"hello_{target}")